summaryrefslogtreecommitdiff
path: root/kvm
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-10-12 12:25:42 +0200
committerMarcelo Tosatti <mtosatti@redhat.com>2009-10-15 12:47:26 -0300
commit1dc78888b8d1bb295d9111b2682e3c3a23d745af (patch)
treef7106a58dd9ae887d0549df603b2aedbf3ffeb2e /kvm
parentSwitch roms/pcbios submodule to qemu-kvm branch (diff)
downloadqemu-kvm-1dc78888b8d1bb295d9111b2682e3c3a23d745af.tar.gz
qemu-kvm-1dc78888b8d1bb295d9111b2682e3c3a23d745af.tar.bz2
qemu-kvm-1dc78888b8d1bb295d9111b2682e3c3a23d745af.zip
Drop kvm/bios/ tree
Equivalent code is now in the roms/pcbios/ submodule. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'kvm')
-rw-r--r--kvm/bios/.cvsignore1
-rw-r--r--kvm/bios/Makefile136
-rw-r--r--kvm/bios/Makefile.in120
-rwxr-xr-xkvm/bios/acpi-dsdt.dsl747
-rw-r--r--kvm/bios/acpi-ssdt.dsl140
-rw-r--r--kvm/bios/apmbios.S365
-rw-r--r--kvm/bios/bios_usage4
-rw-r--r--kvm/bios/biossums.c504
-rwxr-xr-xkvm/bios/makesym.perl31
-rw-r--r--kvm/bios/notes44
-rw-r--r--kvm/bios/rombios.c11456
-rw-r--r--kvm/bios/rombios.h83
-rwxr-xr-xkvm/bios/rombios32.c2749
-rw-r--r--kvm/bios/rombios32.ld22
-rw-r--r--kvm/bios/rombios32start.S119
-rw-r--r--kvm/bios/usage.cc99
-rw-r--r--kvm/bios/vapic.S294
17 files changed, 0 insertions, 16914 deletions
diff --git a/kvm/bios/.cvsignore b/kvm/bios/.cvsignore
deleted file mode 100644
index f3c7a7c5d..000000000
--- a/kvm/bios/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-Makefile
diff --git a/kvm/bios/Makefile b/kvm/bios/Makefile
deleted file mode 100644
index 434d64e8b..000000000
--- a/kvm/bios/Makefile
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright (C) 2001 MandrakeSoft S.A.
-#
-# MandrakeSoft S.A.
-# 43, rue d'Aboukir
-# 75002 Paris - France
-# http://www.linux-mandrake.com/
-# http://www.mandrakesoft.com/
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-# Makefile for the BIOS component of bochs
-
-
-.SUFFIXES: .cc
-
-srcdir = .
-
-
-SHELL = /bin/sh
-
-CXX = g++
-CXXFLAGS = -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES
-
-# cc-option, copied from user/Makefile
-# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
-
-cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
- > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
-
-CFLAGS = -m32
-CFLAGS += $(call cc-option, -fno-stack-protector, "")
-CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
-
-LDFLAGS =
-LIBS = -lm
-RANLIB = ranlib
-
-BCC = bcc
-GCC = gcc $(CFLAGS)
-HOST_CC = gcc
-AS86 = as86
-
-BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev
-LOCAL_CXXFLAGS =
-
-BUILDDATE = `date '+%m/%d/%y'`
-BIOS_BUILD_DATE = "-DBIOS_BUILD_DATE=\"$(BUILDDATE)\""
-#
-# -------- end configurable options --------------------------
-#
-
-
-.cc.o:
- $(CXX) -c $(BX_INCDIRS) $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@
-
-
-bios: biossums BIOS-bochs-latest BIOS-bochs-legacy
-
-clean:
- rm -f *.o *.a *.s _rombios*_.c rombios*.txt rombios*.sym
- rm -f usage biossums rombios16.bin
- rm -f rombios32.bin rombios32.out acpi-dsdt.hex acpi-ssdt.hex
-
-dist-clean: clean
- rm -f Makefile
-
-bios-clean:
- rm -f BIOS-bochs-*
-
-BIOS-bochs-legacy: rombios.c apmbios.S biossums rombios.h
- $(GCC) $(BIOS_BUILD_DATE) -DLEGACY -E -P $< > _rombiosl_.c
- $(BCC) -o rombiosl.s -C-c -D__i86__ -0 -S _rombiosl_.c
- sed -e 's/^\.text//' -e 's/^\.data//' rombiosl.s > _rombiosl_.s
- $(AS86) _rombiosl_.s -b tmpl.bin -u- -w- -g -0 -j -O -l rombiosl.txt
- -perl ${srcdir}/makesym.perl < rombiosl.txt > rombiosl.sym
- mv tmpl.bin $@
- ./biossums $@
- rm -f _rombiosl_.s
-
-
-rombios16.bin: rombios.c apmbios.S biossums rombios.h
- $(GCC) $(BIOS_BUILD_DATE) -E -P $< > _rombios_.c
- $(BCC) -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
- sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
- $(AS86) _rombios_.s -b tmp.bin -u- -w- -g -0 -j -O -l rombios.txt
- -perl ${srcdir}/makesym.perl < rombios.txt > rombios.sym
- mv tmp.bin rombios16.bin
- ./biossums rombios16.bin
- rm -f _rombios_.s
-
-
-rombios32.bin: rombios32.out rombios.h
- objcopy -O binary $< $@
- ./biossums -pad $@
-
-rombios32.out: rombios32start.o rombios32.o vapic.o rombios32.ld
- ld -o $@ -T rombios32.ld rombios32start.o vapic.o rombios32.o
-
-rombios32.o: rombios32.c acpi-dsdt.hex acpi-ssdt.hex
- $(GCC) -m32 -O2 -Wall -c -o $@ $<
-
-acpi-dsdt.hex: acpi-dsdt.dsl
- cpp -P $< $<.i
- iasl -tc -p $@ $<.i
- sed -i -e's/^unsigned char AmlCode/const unsigned char DSDTCode/' $@
- rm $<.i
-
-acpi-ssdt.hex: acpi-ssdt.dsl
- cpp -P $< $<.i
- iasl -tc -p $@ $<.i
- sed -i -e's/^unsigned char AmlCode/const unsigned char SSDTCode/' $@
- rm $<.i
-
-rombios32start.o: rombios32start.S
- $(GCC) -m32 -c -o $@ $<
-
-vapic.o: vapic.S
- $(GCC) -m32 -c -o $@ $<
-
-BIOS-bochs-latest: rombios16.bin rombios32.bin
- cat rombios32.bin rombios16.bin > $@
-
-biossums: biossums.c
- $(HOST_CC) -o biossums biossums.c
diff --git a/kvm/bios/Makefile.in b/kvm/bios/Makefile.in
deleted file mode 100644
index 28ada752b..000000000
--- a/kvm/bios/Makefile.in
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright (C) 2001 MandrakeSoft S.A.
-#
-# MandrakeSoft S.A.
-# 43, rue d'Aboukir
-# 75002 Paris - France
-# http://www.linux-mandrake.com/
-# http://www.mandrakesoft.com/
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-# Makefile for the BIOS component of bochs
-
-
-@SUFFIX_LINE@
-
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-SHELL = /bin/sh
-
-@SET_MAKE@
-
-CXX = @CXX@
-CXXFLAGS = @CXXFLAGS@
-
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-RANLIB = @RANLIB@
-
-BCC = bcc
-GCC = gcc
-GCC32 = gcc -m32 -fno-stack-protector
-AS86 = as86
-
-BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev
-LOCAL_CXXFLAGS =
-
-BUILDDATE = `date '+%m/%d/%y'`
-BIOS_BUILD_DATE = "-DBIOS_BUILD_DATE=\"$(BUILDDATE)\""
-#
-# -------- end configurable options --------------------------
-#
-
-
-.@CPP_SUFFIX@.o:
- $(CXX) -c $(BX_INCDIRS) $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@
-
-
-bios: biossums BIOS-bochs-latest BIOS-bochs-legacy
-
-clean:
- @RMCOMMAND@ *.o *.a *.s _rombios*_.c rombios*.txt rombios*.sym
- @RMCOMMAND@ usage biossums rombios16.bin
- @RMCOMMAND@ rombios32.bin rombios32.out
-
-dist-clean: clean
- @RMCOMMAND@ Makefile
-
-bios-clean:
- @RMCOMMAND@ BIOS-bochs-*
-
-BIOS-bochs-legacy: rombios.c apmbios.S biossums rombios.h
- $(GCC32) $(BIOS_BUILD_DATE) -DLEGACY -E -P $< > _rombiosl_.c
- $(BCC) -o rombiosl.s -C-c -D__i86__ -0 -S _rombiosl_.c
- sed -e 's/^\.text//' -e 's/^\.data//' rombiosl.s > _rombiosl_.s
- $(AS86) _rombiosl_.s -b tmpl.bin -u- -w- -g -0 -j -O -l rombiosl.txt
- -perl ${srcdir}/makesym.perl < rombiosl.txt > rombiosl.sym
- mv tmpl.bin $@
- ./biossums $@
- @RMCOMMAND@ _rombiosl_.s
-
-
-rombios16.bin: rombios.c apmbios.S biossums rombios.h
- $(GCC32) $(BIOS_BUILD_DATE) -E -P $< > _rombios_.c
- $(BCC) -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
- sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
- $(AS86) _rombios_.s -b tmp.bin -u- -w- -g -0 -j -O -l rombios.txt
- -perl ${srcdir}/makesym.perl < rombios.txt > rombios.sym
- mv tmp.bin rombios16.bin
- ./biossums rombios16.bin
- @RMCOMMAND@ _rombios_.s
-
-
-rombios32.bin: rombios32.out rombios.h
- objcopy -O binary $< $@
- ./biossums -pad $@
-
-rombios32.out: rombios32start.o rombios32.o rombios32.ld
- ld -o $@ -T $(srcdir)/rombios32.ld rombios32start.o rombios32.o
-
-rombios32.o: rombios32.c acpi-dsdt.hex
- $(GCC32) -O2 -Wall -c -o $@ $<
-
-ifeq ("1", "0")
-acpi-dsdt.hex: acpi-dsdt.dsl
- cpp -P $< $<.i
- iasl -tc -p $@ $<.i
- rm $<.i
- sed -i -e's/^unsigned/const unsigned/' $@
-endif
-
-rombios32start.o: rombios32start.S
- $(GCC32) -c -o $@ $<
-
-BIOS-bochs-latest: rombios16.bin rombios32.bin
- cat rombios32.bin rombios16.bin > $@
-
-biossums: biossums.o
diff --git a/kvm/bios/acpi-dsdt.dsl b/kvm/bios/acpi-dsdt.dsl
deleted file mode 100755
index 26fc7add7..000000000
--- a/kvm/bios/acpi-dsdt.dsl
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * Bochs/QEMU ACPI DSDT ASL definition
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-DefinitionBlock (
- "acpi-dsdt.aml", // Output Filename
- "DSDT", // Signature
- 0x01, // DSDT Compliance Revision
- "BXPC", // OEMID
- "BXDSDT", // TABLE ID
- 0x1 // OEM Revision
- )
-{
- Scope (\)
- {
- /* Debug Output */
- OperationRegion (DBG, SystemIO, 0xb044, 0x04)
- Field (DBG, DWordAcc, NoLock, Preserve)
- {
- DBGL, 32,
- }
- }
-
-
- /* PCI Bus definition */
- Scope(\_SB) {
- Device(PCI0) {
- Name (_HID, EisaId ("PNP0A03"))
- Name (_ADR, 0x00)
- Name (_UID, 1)
- Name(_PRT, Package() {
- /* PCI IRQ routing table, example from ACPI 2.0a specification,
- section 6.2.8.1 */
- /* Note: we provide the same info as the PCI routing
- table of the Bochs BIOS */
-
-#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
- Package() { nr##ffff, 0, lnk0, 0 }, \
- Package() { nr##ffff, 1, lnk1, 0 }, \
- Package() { nr##ffff, 2, lnk2, 0 }, \
- Package() { nr##ffff, 3, lnk3, 0 }
-
-#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
-#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
-#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
-#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
-
- prt_slot0(0x0000),
- prt_slot1(0x0001),
- prt_slot2(0x0002),
- prt_slot3(0x0003),
- prt_slot0(0x0004),
- prt_slot1(0x0005),
- prt_slot2(0x0006),
- prt_slot3(0x0007),
- prt_slot0(0x0008),
- prt_slot1(0x0009),
- prt_slot2(0x000a),
- prt_slot3(0x000b),
- prt_slot0(0x000c),
- prt_slot1(0x000d),
- prt_slot2(0x000e),
- prt_slot3(0x000f),
- prt_slot0(0x0010),
- prt_slot1(0x0011),
- prt_slot2(0x0012),
- prt_slot3(0x0013),
- prt_slot0(0x0014),
- prt_slot1(0x0015),
- prt_slot2(0x0016),
- prt_slot3(0x0017),
- prt_slot0(0x0018),
- prt_slot1(0x0019),
- prt_slot2(0x001a),
- prt_slot3(0x001b),
- prt_slot0(0x001c),
- prt_slot1(0x001d),
- prt_slot2(0x001e),
- prt_slot3(0x001f),
- })
-
- OperationRegion(PCST, SystemIO, 0xae00, 0x08)
- Field (PCST, DWordAcc, NoLock, WriteAsZeros)
- {
- PCIU, 32,
- PCID, 32,
- }
-
- OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
- Field (SEJ, DWordAcc, NoLock, WriteAsZeros)
- {
- B0EJ, 32,
- }
-
-#define hotplug_slot(name, nr) \
- Device (S##name) { \
- Name (_ADR, nr##0000) \
- Method (_EJ0,1) { \
- Store(ShiftLeft(1, nr), B0EJ) \
- Return (0x0) \
- } \
- Name (_SUN, name) \
- }
-
- hotplug_slot(1, 0x0001)
- hotplug_slot(2, 0x0002)
- hotplug_slot(3, 0x0003)
- hotplug_slot(4, 0x0004)
- hotplug_slot(5, 0x0005)
- hotplug_slot(6, 0x0006)
- hotplug_slot(7, 0x0007)
- hotplug_slot(8, 0x0008)
- hotplug_slot(9, 0x0009)
- hotplug_slot(10, 0x000a)
- hotplug_slot(11, 0x000b)
- hotplug_slot(12, 0x000c)
- hotplug_slot(13, 0x000d)
- hotplug_slot(14, 0x000e)
- hotplug_slot(15, 0x000f)
- hotplug_slot(16, 0x0010)
- hotplug_slot(17, 0x0011)
- hotplug_slot(18, 0x0012)
- hotplug_slot(19, 0x0013)
- hotplug_slot(20, 0x0014)
- hotplug_slot(21, 0x0015)
- hotplug_slot(22, 0x0016)
- hotplug_slot(23, 0x0017)
- hotplug_slot(24, 0x0018)
- hotplug_slot(25, 0x0019)
- hotplug_slot(26, 0x001a)
- hotplug_slot(27, 0x001b)
- hotplug_slot(28, 0x001c)
- hotplug_slot(29, 0x001d)
- hotplug_slot(30, 0x001e)
- hotplug_slot(31, 0x001f)
-
- Name (_CRS, ResourceTemplate ()
- {
- WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
- 0x0000, // Address Space Granularity
- 0x0000, // Address Range Minimum
- 0x00FF, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0x0100, // Address Length
- ,, )
- IO (Decode16,
- 0x0CF8, // Address Range Minimum
- 0x0CF8, // Address Range Maximum
- 0x01, // Address Alignment
- 0x08, // Address Length
- )
- WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
- 0x0000, // Address Space Granularity
- 0x0000, // Address Range Minimum
- 0x0CF7, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0x0CF8, // Address Length
- ,, , TypeStatic)
- WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
- 0x0000, // Address Space Granularity
- 0x0D00, // Address Range Minimum
- 0xFFFF, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0xF300, // Address Length
- ,, , TypeStatic)
- DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0x000A0000, // Address Range Minimum
- 0x000BFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x00020000, // Address Length
- ,, , AddressRangeMemory, TypeStatic)
- DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0xE0000000, // Address Range Minimum
- 0xFEBFFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x1EC00000, // Address Length
- ,, , AddressRangeMemory, TypeStatic)
- })
- }
-#ifdef BX_QEMU
- Device(HPET) {
- Name(_HID, EISAID("PNP0103"))
- Name(_UID, 0)
- Method (_STA, 0, NotSerialized) {
- Return(0x0F)
- }
- Name(_CRS, ResourceTemplate() {
- DWordMemory(
- ResourceConsumer, PosDecode, MinFixed, MaxFixed,
- NonCacheable, ReadWrite,
- 0x00000000,
- 0xFED00000,
- 0xFED003FF,
- 0x00000000,
- 0x00000400 /* 1K memory: FED00000 - FED003FF */
- )
- })
- }
-#endif
- }
-
- Scope(\_SB.PCI0) {
- Device (VGA) {
- Name (_ADR, 0x00020000)
- Method (_S1D, 0, NotSerialized)
- {
- Return (0x00)
- }
- Method (_S2D, 0, NotSerialized)
- {
- Return (0x00)
- }
- Method (_S3D, 0, NotSerialized)
- {
- Return (0x00)
- }
- }
-
- /* PIIX3 ISA bridge */
- Device (ISA) {
- Name (_ADR, 0x00010000)
-
- /* PIIX PCI to ISA irq remapping */
- OperationRegion (P40C, PCI_Config, 0x60, 0x04)
-
- /* Real-time clock */
- Device (RTC)
- {
- Name (_HID, EisaId ("PNP0B00"))
- Name (_CRS, ResourceTemplate ()
- {
- IO (Decode16, 0x0070, 0x0070, 0x10, 0x02)
- IRQNoFlags () {8}
- IO (Decode16, 0x0072, 0x0072, 0x02, 0x06)
- })
- }
-
- /* Keyboard seems to be important for WinXP install */
- Device (KBD)
- {
- Name (_HID, EisaId ("PNP0303"))
- Method (_STA, 0, NotSerialized)
- {
- Return (0x0f)
- }
-
- Method (_CRS, 0, NotSerialized)
- {
- Name (TMP, ResourceTemplate ()
- {
- IO (Decode16,
- 0x0060, // Address Range Minimum
- 0x0060, // Address Range Maximum
- 0x01, // Address Alignment
- 0x01, // Address Length
- )
- IO (Decode16,
- 0x0064, // Address Range Minimum
- 0x0064, // Address Range Maximum
- 0x01, // Address Alignment
- 0x01, // Address Length
- )
- IRQNoFlags ()
- {1}
- })
- Return (TMP)
- }
- }
-
- /* PS/2 mouse */
- Device (MOU)
- {
- Name (_HID, EisaId ("PNP0F13"))
- Method (_STA, 0, NotSerialized)
- {
- Return (0x0f)
- }
-
- Method (_CRS, 0, NotSerialized)
- {
- Name (TMP, ResourceTemplate ()
- {
- IRQNoFlags () {12}
- })
- Return (TMP)
- }
- }
-
- /* PS/2 floppy controller */
- Device (FDC0)
- {
- Name (_HID, EisaId ("PNP0700"))
- Method (_STA, 0, NotSerialized)
- {
- Return (0x0F)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
- IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
- IRQNoFlags () {6}
- DMA (Compatibility, NotBusMaster, Transfer8) {2}
- })
- Return (BUF0)
- }
- }
-
- /* Parallel port */
- Device (LPT)
- {
- Name (_HID, EisaId ("PNP0400"))
- Method (_STA, 0, NotSerialized)
- {
- Store (\_SB.PCI0.PX13.DRSA, Local0)
- And (Local0, 0x80000000, Local0)
- If (LEqual (Local0, 0))
- {
- Return (0x00)
- }
- Else
- {
- Return (0x0F)
- }
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
- IRQNoFlags () {7}
- })
- Return (BUF0)
- }
- }
-
- /* Serial Ports */
- Device (COM1)
- {
- Name (_HID, EisaId ("PNP0501"))
- Name (_UID, 0x01)
- Method (_STA, 0, NotSerialized)
- {
- Store (\_SB.PCI0.PX13.DRSC, Local0)
- And (Local0, 0x08000000, Local0)
- If (LEqual (Local0, 0))
- {
- Return (0x00)
- }
- Else
- {
- Return (0x0F)
- }
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
- IRQNoFlags () {4}
- })
- Return (BUF0)
- }
- }
-
- Device (COM2)
- {
- Name (_HID, EisaId ("PNP0501"))
- Name (_UID, 0x02)
- Method (_STA, 0, NotSerialized)
- {
- Store (\_SB.PCI0.PX13.DRSC, Local0)
- And (Local0, 0x80000000, Local0)
- If (LEqual (Local0, 0))
- {
- Return (0x00)
- }
- Else
- {
- Return (0x0F)
- }
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
- IRQNoFlags () {3}
- })
- Return (BUF0)
- }
- }
- }
-
- /* PIIX4 PM */
- Device (PX13) {
- Name (_ADR, 0x00010003)
-
- OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
- Field (P13C, DWordAcc, NoLock, Preserve)
- {
- DRSA, 32,
- DRSB, 32,
- DRSC, 32,
- DRSE, 32,
- DRSF, 32,
- DRSG, 32,
- DRSH, 32,
- DRSI, 32,
- DRSJ, 32
- }
- }
- }
-
- /* PCI IRQs */
- Scope(\_SB) {
- Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
- {
- PRQ0, 8,
- PRQ1, 8,
- PRQ2, 8,
- PRQ3, 8
- }
-
- Device(LNKA){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 1)
- Name(_PRS, ResourceTemplate(){
- Interrupt (, Level, ActiveHigh, Shared)
- { 5, 10, 11 }
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ0, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ0, 0x80, PRQ0)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- Interrupt (, Level, ActiveHigh, Shared)
- {1}
- })
- CreateDWordField (PRR0, 0x05, TMP)
- Store (PRQ0, Local0)
- If (LLess (Local0, 0x80))
- {
- Store (Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateDWordField (Arg0, 0x05, TMP)
- Store (TMP, PRQ0)
- }
- }
- Device(LNKB){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 2)
- Name(_PRS, ResourceTemplate(){
- Interrupt (, Level, ActiveHigh, Shared)
- { 5, 10, 11 }
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ1, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ1, 0x80, PRQ1)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- Interrupt (, Level, ActiveHigh, Shared)
- {1}
- })
- CreateDWordField (PRR0, 0x05, TMP)
- Store (PRQ1, Local0)
- If (LLess (Local0, 0x80))
- {
- Store (Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateDWordField (Arg0, 0x05, TMP)
- Store (TMP, PRQ1)
- }
- }
- Device(LNKC){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 3)
- Name(_PRS, ResourceTemplate(){
- Interrupt (, Level, ActiveHigh, Shared)
- { 5, 10, 11 }
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ2, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ2, 0x80, PRQ2)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- Interrupt (, Level, ActiveHigh, Shared)
- {1}
- })
- CreateDWordField (PRR0, 0x05, TMP)
- Store (PRQ2, Local0)
- If (LLess (Local0, 0x80))
- {
- Store (Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateDWordField (Arg0, 0x05, TMP)
- Store (TMP, PRQ2)
- }
- }
- Device(LNKD){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 4)
- Name(_PRS, ResourceTemplate(){
- Interrupt (, Level, ActiveHigh, Shared)
- { 5, 10, 11 }
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ3, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ3, 0x80, PRQ3)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- Interrupt (, Level, ActiveHigh, Shared)
- {1}
- })
- CreateDWordField (PRR0, 0x05, TMP)
- Store (PRQ3, Local0)
- If (LLess (Local0, 0x80))
- {
- Store (Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateDWordField (Arg0, 0x05, TMP)
- Store (TMP, PRQ3)
- }
- }
- }
-
- /*
- * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
- * must match piix4 emulation.
- */
- Name (\_S3, Package (0x04)
- {
- 0x01, /* PM1a_CNT.SLP_TYP */
- 0x01, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- Name (\_S4, Package (0x04)
- {
- Zero, /* PM1a_CNT.SLP_TYP */
- Zero, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- Name (\_S5, Package (0x04)
- {
- Zero, /* PM1a_CNT.SLP_TYP */
- Zero, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
-
- Scope (\_GPE)
- {
- Name(_HID, "ACPI0006")
-
- Method(_L00) {
- Return(0x01)
- }
-
-#define gen_pci_hotplug(nr) \
- If (And(\_SB.PCI0.PCIU, ShiftLeft(1, nr))) { \
- Notify(\_SB.PCI0.S##nr, 1) \
- } \
- If (And(\_SB.PCI0.PCID, ShiftLeft(1, nr))) { \
- Notify(\_SB.PCI0.S##nr, 3) \
- }
-
- Method(_L01) {
- gen_pci_hotplug(1)
- gen_pci_hotplug(2)
- gen_pci_hotplug(3)
- gen_pci_hotplug(4)
- gen_pci_hotplug(5)
- gen_pci_hotplug(6)
- gen_pci_hotplug(7)
- gen_pci_hotplug(8)
- gen_pci_hotplug(9)
- gen_pci_hotplug(10)
- gen_pci_hotplug(11)
- gen_pci_hotplug(12)
- gen_pci_hotplug(13)
- gen_pci_hotplug(14)
- gen_pci_hotplug(15)
- gen_pci_hotplug(16)
- gen_pci_hotplug(17)
- gen_pci_hotplug(18)
- gen_pci_hotplug(19)
- gen_pci_hotplug(20)
- gen_pci_hotplug(21)
- gen_pci_hotplug(22)
- gen_pci_hotplug(23)
- gen_pci_hotplug(24)
- gen_pci_hotplug(25)
- gen_pci_hotplug(26)
- gen_pci_hotplug(27)
- gen_pci_hotplug(28)
- gen_pci_hotplug(29)
- gen_pci_hotplug(30)
- gen_pci_hotplug(31)
-
- Return(0x01)
- }
-
- /*
- * Method _02 will be provided by the SSDT as it needs to call
- * into the Processor methods (_PR.PRSC()).
- */
-
- Method(_L03) {
- Return(0x01)
- }
- Method(_L04) {
- Return(0x01)
- }
- Method(_L05) {
- Return(0x01)
- }
- Method(_L06) {
- Return(0x01)
- }
- Method(_L07) {
- Return(0x01)
- }
- Method(_L08) {
- Return(0x01)
- }
- Method(_L09) {
- Return(0x01)
- }
- Method(_L0A) {
- Return(0x01)
- }
- Method(_L0B) {
- Return(0x01)
- }
- Method(_L0C) {
- Return(0x01)
- }
- Method(_L0D) {
- Return(0x01)
- }
- Method(_L0E) {
- Return(0x01)
- }
- Method(_L0F) {
- Return(0x01)
- }
- }
-}
diff --git a/kvm/bios/acpi-ssdt.dsl b/kvm/bios/acpi-ssdt.dsl
deleted file mode 100644
index d998867d7..000000000
--- a/kvm/bios/acpi-ssdt.dsl
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Bochs/QEMU ACPI SSDT ASL definition
- *
- * Copyright (c) 2006 Fabrice Bellard
- * Copyright (c) 2009 SGI, Jes Sorensen <jes@sgi.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-DefinitionBlock (
- "acpi-ssdt.aml", // Output Filename
- "SSDT", // Signature
- 0x01, // DSDT Compliance Revision
- "BXPC", // OEMID
- "BXSSDT", // TABLE ID
- 0x1 // OEM Revision
- )
-{
- Scope (\_PR)
- {
- /* pointer to first element of MADT APIC structures */
- OperationRegion(ATPR, SystemMemory, 0x0514, 4)
- Field (ATPR, DwordAcc, NoLock, Preserve)
- {
- ATP, 32
- }
-
-#define madt_addr(nr) Add (ATP, Multiply(nr, 8))
-
-#define gen_processor(nr, name) \
- Processor (C##name, nr, 0x0000b010, 0x06) { \
- OperationRegion (MATR, SystemMemory, madt_addr(nr), 8) \
- Field (MATR, ByteAcc, NoLock, Preserve) \
- { \
- MAT, 64 \
- } \
- Field (MATR, ByteAcc, NoLock, Preserve) \
- { \
- Offset(4), \
- FLG, 1 \
- } \
- Method(_MAT, 0) { \
- Return(MAT) \
- } \
- Method (_STA) { \
- If (FLG) { Return(0xF) } Else { Return(0x9) } \
- } \
- } \
-
-
- gen_processor(0, 0)
- gen_processor(1, 1)
- gen_processor(2, 2)
- gen_processor(3, 3)
- gen_processor(4, 4)
- gen_processor(5, 5)
- gen_processor(6, 6)
- gen_processor(7, 7)
- gen_processor(8, 8)
- gen_processor(9, 9)
- gen_processor(10, A)
- gen_processor(11, B)
- gen_processor(12, C)
- gen_processor(13, D)
- gen_processor(14, E)
-
- Method (NTFY, 2) {
-#define gen_ntfy(nr) \
- If (LEqual(Arg0, 0x##nr)) { \
- If (LNotEqual(Arg1, \_PR.C##nr.FLG)) { \
- Store (Arg1, \_PR.C##nr.FLG) \
- If (LEqual(Arg1, 1)) { \
- Notify(C##nr, 1) \
- } Else { \
- Notify(C##nr, 3) \
- } \
- } \
- }
- gen_ntfy(0)
- gen_ntfy(1)
- gen_ntfy(2)
- gen_ntfy(3)
- gen_ntfy(4)
- gen_ntfy(5)
- gen_ntfy(6)
- gen_ntfy(7)
- gen_ntfy(8)
- gen_ntfy(9)
- gen_ntfy(A)
- gen_ntfy(B)
- gen_ntfy(C)
- gen_ntfy(D)
- gen_ntfy(E)
- Return(One)
- }
-
- OperationRegion(PRST, SystemIO, 0xaf00, 32)
- Field (PRST, ByteAcc, NoLock, Preserve)
- {
- PRS, 256
- }
-
- Method(PRSC, 0) {
- Store(PRS, Local3)
- Store(Zero, Local0)
- While(LLess(Local0, 32)) {
- Store(Zero, Local1)
- Store(DerefOf(Index(Local3, Local0)), Local2)
- While(LLess(Local1, 8)) {
- NTFY(Add(Multiply(Local0, 8), Local1),
- And(Local2, 1))
- ShiftRight(Local2, 1, Local2)
- Increment(Local1)
- }
- Increment(Local0)
- }
- Return(One)
- }
- }
-
- /*
- * Add the missing _L02 method for CPU notification
- */
- Scope (\_GPE)
- {
- Method(_L02) {
- Return(\_PR.PRSC())
- }
- }
-}
diff --git a/kvm/bios/apmbios.S b/kvm/bios/apmbios.S
deleted file mode 100644
index 41c9e7ef1..000000000
--- a/kvm/bios/apmbios.S
+++ /dev/null
@@ -1,365 +0,0 @@
-// APM BIOS support for the Bochs BIOS
-// Copyright (C) 2004 Fabrice Bellard
-//
-// Debugging extensions, 16-bit interface and extended power options
-// Copyright (C) 2005 Struan Bartlett
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-#if defined(APM_REAL)
-#define APMSYM(s) apmreal_ ## s
-#elif defined(APM_PROT16)
-#define APMSYM(s) apm16_ ## s
-#elif defined(APM_PROT32)
-#define APMSYM(s) apm32_ ## s
-#else
-#error unsupported APM mode
-#endif
-
-APMSYM(out_str):
- push eax
- push ebx
- mov ebx, eax
-APMSYM(out_str1):
- SEG CS
- mov al, byte ptr [bx]
- cmp al, #0
- je APMSYM(out_str2)
- outb dx, al
- inc ebx
- jmp APMSYM(out_str1)
-APMSYM(out_str2):
- pop ebx
- pop eax
- ret
-
-APMSYM(07_poweroff_str):
- .ascii "Shutdown"
- db 0
-APMSYM(07_suspend_str):
- .ascii "Suspend"
- db 0
-APMSYM(07_standby_str):
- .ascii "Standby"
- db 0
-
-#if DEBUG_APM
-APMSYM(put_str):
- push edx
- mov dx, #INFO_PORT
- call APMSYM(out_str)
- pop edx
- ret
-
-; print the hex number in eax
-APMSYM(put_num):
- push eax
- push ebx
- push ecx
- push edx
- mov ecx, eax
- mov bx, #8
- mov dx, #INFO_PORT
-APMSYM(put_num1):
- mov eax, ecx
- shr eax, #28
- add al, #0x30
- cmp al, #0x39
- jbe APMSYM(put_num2)
- add al, #0x27
-APMSYM(put_num2):
- outb dx, al
- shl ecx, #4
- dec bx
- jne APMSYM(put_num1)
- pop edx
- pop ecx
- pop ebx
- pop eax
- ret
-
-APMSYM(put_reg):
- outb dx, al
- shr eax, #8
- outb dx, al
- shr eax, #8
- outb dx, al
- shr eax, #8
- outb dx, al
-
- mov eax,ebx
- call APMSYM(put_num)
-
- mov al, #0x3b
- outb dx,al
- mov al, #0x20
- outb dx,al
- ret
-
-APMSYM(put_regs):
- push eax
- push edx
- push ebx
- mov dx, #INFO_PORT
-
- mov ebx, eax
- mov eax, #0x3d584145 // 'EAX='
- call APMSYM(put_reg)
- pop ebx
- push ebx
- mov eax, #0x3d584245 // 'EBX='
- call APMSYM(put_reg)
- mov ebx, ecx
- mov eax, #0x3d584345 // 'ECX='
- call APMSYM(put_reg)
- mov ebx, edx
- mov eax, #0x3d584445 // 'EDX='
- call APMSYM(put_reg)
- mov ebx, esi
- mov eax, #0x3d495345 // 'ESI='
- call APMSYM(put_reg)
- mov ebx, edi
- mov eax, #0x3d494445 // 'EDI='
- call APMSYM(put_reg)
-
- mov al, #0x0a
- outb dx, al
- pop ebx
- pop edx
- pop eax
- ret
-#endif
-
-#if defined(APM_PROT32)
-_apm32_entry:
-#endif
-#if defined(APM_PROT16)
-_apm16_entry:
-#endif
- pushf
-
-#if defined(APM_REAL)
-_apmreal_entry:
-#endif
-
-#if DEBUG_APM
- call APMSYM(put_regs)
-#endif
-
-#if defined(APM_REAL)
-;-----------------
-; APM installation check
-APMSYM(00):
- cmp al, #0x00
- jne APMSYM(01)
-
- mov ah, #1 // APM major version
- mov al, #2 // APM minor version
-
- mov bh, #0x50 // 'P'
- mov bl, #0x4d // 'M'
-
- // bit 0 : 16 bit interface supported
- // bit 1 : 32 bit interface supported
- mov cx, #0x3
- jmp APMSYM(ok)
-
-;-----------------
-; APM real mode interface connect
-APMSYM(01):
- cmp al, #0x01
- jne APMSYM(02)
- jmp APMSYM(ok)
-
-;-----------------
-; APM 16 bit protected mode interface connect
-APMSYM(02):
- cmp al, #0x02
- jne APMSYM(03)
-
- mov bx, #_apm16_entry
-
- mov ax, #0xf000 // 16 bit code segment base
- mov si, #0xfff0 // 16 bit code segment size
- mov cx, #0xf000 // data segment address
- mov di, #0xfff0 // data segment length
- jmp APMSYM(ok)
-
-;-----------------
-; APM 32 bit protected mode interface connect
-APMSYM(03):
- cmp al, #0x03
- jne APMSYM(04)
- mov ax, #0xf000 // 32 bit code segment base
- mov ebx, #_apm32_entry
- mov cx, #0xf000 // 16 bit code segment base
- // 32 bit code segment size (low 16 bits)
- // 16 bit code segment size (high 16 bits)
- mov esi, #0xfff0fff0
- mov dx, #0xf000 // data segment address
- mov di, #0xfff0 // data segment length
- jmp APMSYM(ok)
-#endif
-
-;-----------------
-; APM interface disconnect
-APMSYM(04):
- cmp al, #0x04
- jne APMSYM(05)
- jmp APMSYM(ok)
-
-;-----------------
-; APM cpu idle
-APMSYM(05):
- cmp al, #0x05
- jne APMSYM(07)
- sti
- hlt
- jmp APMSYM(ok)
-
-;-----------------
-; APM Set Power State
-APMSYM(07):
- cmp al, #0x07
- jne APMSYM(08)
-
- cmp bx, #1
- jne APMSYM(ok)
-
- cmp cx, #3
- je APMSYM(07_poweroff)
-
- cmp cx, #2
- je APMSYM(07_suspend)
-
- cmp cx, #1
- je APMSYM(07_standby)
-
- jne APMSYM(ok)
-
-APMSYM(07_poweroff):
- // send power off event to emulator
- cli
- mov dx, #0x8900
- mov ax, #APMSYM(07_poweroff_str)
- call APMSYM(out_str)
-
-APMSYM(07_1):
- hlt
- jmp APMSYM(07_1)
-
-APMSYM(07_suspend):
- push edx
- mov dx, #0x8900
- mov ax, #APMSYM(07_suspend_str)
- call APMSYM(out_str)
- pop edx
- jmp APMSYM(ok)
-
-APMSYM(07_standby):
- push edx
- mov dx, #0x8900
- mov ax, #APMSYM(07_standby_str)
- call APMSYM(out_str)
- pop edx
- jmp APMSYM(ok)
-
-;-----------------
-; APM Enable / Disable
-APMSYM(08):
- cmp al, #0x08
- jne APMSYM(0a)
-
- jmp APMSYM(ok)
-
-;-----------------
-; Get Power Status
-APMSYM(0a):
- cmp al, #0x0a
- jne APMSYM(0b)
- mov bh, #0x01 // on line
- // mov bh, #0x02 // battery
- mov bl, #0xff // unknown battery status
- // mov bl, #0x03 // charging
- mov ch, #0x80 // no system battery
- // mov ch, #0x8 // charging
- mov cl, #0xff // unknown remaining time
- // mov cl, #50
- mov dx, #0xffff // unknown remaining time
- mov si, #0 // zero battery
- // mov si, #1 // one battery
- jmp APMSYM(ok)
-
-;-----------------
-; Get PM Event
-APMSYM(0b):
- cmp al, #0x0b
- jne APMSYM(0e)
- mov ah, #0x80 // no event pending
- jmp APMSYM(error)
-
-;-----------------
-; APM Driver Version
-APMSYM(0e):
- cmp al, #0x0e
- jne APMSYM(0f)
-
- mov ah, #1
- mov al, #2
-
- jmp APMSYM(ok)
-
-;-----------------
-; APM Engage / Disengage
-APMSYM(0f):
- cmp al, #0x0f
- jne APMSYM(10)
-
- jmp APMSYM(ok)
-
-;-----------------
-; APM Get Capabilities
-APMSYM(10):
- cmp al, #0x10
- jne APMSYM(unimplemented)
-
- mov bl, #0
- mov cx, #0
-
- jmp APMSYM(ok)
-
-;-----------------
-APMSYM(ok):
- popf
- clc
-#if defined(APM_REAL)
- jmp iret_modify_cf
-#else
- retf
-#endif
-APMSYM(unimplemented):
-APMSYM(error):
- popf
- stc
-#if defined(APM_REAL)
- jmp iret_modify_cf
-#else
- retf
-#endif
-
-#undef APM_PROT32
-#undef APM_PROT16
-#undef APM_REAL
-#undef APMSYM
diff --git a/kvm/bios/bios_usage b/kvm/bios/bios_usage
deleted file mode 100644
index 8019ef630..000000000
--- a/kvm/bios/bios_usage
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/csh -f
-gcc -E rombios.c | grep "^\.org" | sed -e 's/\.org //' | sed -e 's/ .*//' | sort >! temp.usage
-usage rombios.bin temp.usage
-/bin/rm temp.usage
diff --git a/kvm/bios/biossums.c b/kvm/bios/biossums.c
deleted file mode 100644
index 032ac23c3..000000000
--- a/kvm/bios/biossums.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * $Id: biossums.c,v 1.4 2007/05/28 08:09:13 vruppert Exp $
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* biossums.c --- written by Eike W. for the Bochs BIOS */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-typedef unsigned char byte;
-
-void check( int value, char* message );
-
-#define LEN_BIOS_DATA 0x10000
-#define MAX_OFFSET (LEN_BIOS_DATA - 1)
-
-
-#define BIOS_OFFSET 0xFFFF
-
-long chksum_bios_get_offset( byte* data, long offset );
-byte chksum_bios_calc_value( byte* data, long offset );
-byte chksum_bios_get_value( byte* data, long offset );
-void chksum_bios_set_value( byte* data, long offset, byte value );
-
-
-#define _32__LEN 9
-#define _32__CHKSUM 10
-
-#define _32__MINHDR 16
-
-long chksum__32__get_offset( byte* data, long offset );
-byte chksum__32__calc_value( byte* data, long offset );
-byte chksum__32__get_value( byte* data, long offset );
-void chksum__32__set_value( byte* data, long offset, byte value );
-
-
-#define _MP__LEN 8
-#define _MP__CHKSUM 10
-
-#define _MP__MINHDR 16
-
-long chksum__mp__get_offset( byte* data, long offset );
-byte chksum__mp__calc_value( byte* data, long offset );
-byte chksum__mp__get_value( byte* data, long offset );
-void chksum__mp__set_value( byte* data, long offset, byte value );
-
-
-#define PCMP_BASELEN 4
-#define PCMP_CHKSUM 7
-#define PCMP_EXT_LEN 40
-#define PCMP_EXT_CHKSUM 42
-
-#define PCMP_MINHDR 42
-
-long chksum_pcmp_get_offset( byte* data, long offset );
-byte chksum_pcmp_calc_value( byte* data, long offset );
-byte chksum_pcmp_get_value( byte* data, long offset );
-void chksum_pcmp_set_value( byte* data, long offset, byte value );
-
-
-#define _PIR_LEN 6
-#define _PIR_CHKSUM 31
-
-#define _PIR_MINHDR 32
-
-long chksum__pir_get_offset( byte *data, long offset );
-byte chksum__pir_calc_value( byte* data, long offset );
-byte chksum__pir_get_value( byte* data, long offset );
-void chksum__pir_set_value( byte* data, long offset, byte value );
-
-
-byte bios_data[LEN_BIOS_DATA];
-long bios_len;
-
-
-int main(int argc, char* argv[]) {
-
- FILE* stream;
- long offset, tmp_offset;
- byte cur_val = 0, new_val = 0;
- int arg = 1, hits, pad = 0;
-
-
- if ((argc == 3) && (!strcmp(argv[1], "-pad"))) {
- pad = 1;
- arg = 2;
- } else if (argc != 2) {
- printf("Error. Need a file-name as an argument.\n");
- exit(EXIT_FAILURE);
- }
- memset(bios_data, 0xff, LEN_BIOS_DATA);
-
- if ((stream = fopen(argv[arg], "rb")) == NULL) {
- printf("Error opening %s for reading.\n", argv[arg]);
- exit(EXIT_FAILURE);
- }
- bios_len = fread(bios_data, 1, LEN_BIOS_DATA, stream);
- if ((bios_len < LEN_BIOS_DATA) && (pad == 0)) {
- printf("Error reading 64KBytes from %s.\n", argv[arg]);
- fclose(stream);
- exit(EXIT_FAILURE);
- }
- fclose(stream);
- if (pad == 1) goto write_bios;
-
- hits = 0;
- offset = 0L;
- while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) {
- offset = tmp_offset;
- cur_val = chksum__32__get_value( bios_data, offset );
- new_val = chksum__32__calc_value( bios_data, offset );
- printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset );
- printf( "Current checksum: 0x%02X\n", cur_val );
- printf( "Calculated checksum: 0x%02X ", new_val );
- hits++;
- }
- if( hits == 1 && cur_val != new_val ) {
- printf( "Setting checksum." );
- chksum__32__set_value( bios_data, offset, new_val );
- }
- if( hits >= 2 ) {
- printf( "Multiple PCI headers! No checksum set." );
- }
- if( hits ) {
- printf( "\n" );
- }
-
-
- hits = 0;
- offset = 0L;
- while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) {
- offset = tmp_offset;
- cur_val = chksum__mp__get_value( bios_data, offset );
- new_val = chksum__mp__calc_value( bios_data, offset );
- printf( "\n\nMP header at: 0x%4lX\n", offset );
- printf( "Current checksum: 0x%02X\n", cur_val );
- printf( "Calculated checksum: 0x%02X ", new_val );
- hits++;
- }
- if( hits == 1 && cur_val != new_val ) {
- printf( "Setting checksum." );
- chksum__mp__set_value( bios_data, offset, new_val );
- }
- if( hits >= 2 ) {
- printf( "Warning! Multiple MP headers. No checksum set." );
- }
- if( hits ) {
- printf( "\n" );
- }
-
-
- hits = 0;
- offset = 0L;
- while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) {
- offset = tmp_offset;
- cur_val = chksum_pcmp_get_value( bios_data, offset );
- new_val = chksum_pcmp_calc_value( bios_data, offset );
- printf( "\n\nPCMP header at: 0x%4lX\n", offset );
- printf( "Current checksum: 0x%02X\n", cur_val );
- printf( "Calculated checksum: 0x%02X ", new_val );
- hits++;
- }
- if( hits == 1 && cur_val != new_val ) {
- printf( "Setting checksum." );
- chksum_pcmp_set_value( bios_data, offset, new_val );
- }
- if( hits >= 2 ) {
- printf( "Warning! Multiple PCMP headers. No checksum set." );
- }
- if( hits ) {
- printf( "\n" );
- }
-
-
- hits = 0;
- offset = 0L;
- while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) {
- offset = tmp_offset;
- cur_val = chksum__pir_get_value( bios_data, offset );
- new_val = chksum__pir_calc_value( bios_data, offset );
- printf( "\n\n$PIR header at: 0x%4lX\n", offset );
- printf( "Current checksum: 0x%02X\n", cur_val );
- printf( "Calculated checksum: 0x%02X\n ", new_val );
- hits++;
- }
- if( hits == 1 && cur_val != new_val ) {
- printf( "Setting checksum." );
- chksum__pir_set_value( bios_data, offset, new_val );
- }
- if( hits >= 2 ) {
- printf( "Warning! Multiple $PIR headers. No checksum set." );
- }
- if( hits ) {
- printf( "\n" );
- }
-
-
- offset = 0L;
- offset = chksum_bios_get_offset( bios_data, offset );
- cur_val = chksum_bios_get_value( bios_data, offset );
- new_val = chksum_bios_calc_value( bios_data, offset );
- printf( "\n\nBios checksum at: 0x%4lX\n", offset );
- printf( "Current checksum: 0x%02X\n", cur_val );
- printf( "Calculated checksum: 0x%02X ", new_val );
- if( cur_val != new_val ) {
- printf( "Setting checksum." );
- chksum_bios_set_value( bios_data, offset, new_val );
- }
- printf( "\n" );
-
-write_bios:
- if ((stream = fopen(argv[arg], "wb")) == NULL) {
- printf("Error opening %s for writing.\n", argv[arg]);
- exit(EXIT_FAILURE);
- }
- if (fwrite(bios_data, 1, LEN_BIOS_DATA, stream) < LEN_BIOS_DATA) {
- printf("Error writing 64KBytes to %s.\n", argv[arg]);
- fclose(stream);
- exit(EXIT_FAILURE);
- }
- fclose(stream);
-
- return(EXIT_SUCCESS);
-}
-
-
-void check(int okay, char* message) {
-
- if (!okay) {
- printf("\n\nError. %s.\n", message);
- exit(EXIT_FAILURE);
- }
-}
-
-
-long chksum_bios_get_offset( byte* data, long offset ) {
-
- return( BIOS_OFFSET );
-}
-
-
-byte chksum_bios_calc_value( byte* data, long offset ) {
-
- int i;
- byte sum;
-
- sum = 0;
- for( i = 0; i < MAX_OFFSET; i++ ) {
- sum = sum + *( data + i );
- }
- sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
- return( sum );
-}
-
-
-byte chksum_bios_get_value( byte* data, long offset ) {
-
- return( *( data + BIOS_OFFSET ) );
-}
-
-
-void chksum_bios_set_value( byte* data, long offset, byte value ) {
-
- *( data + BIOS_OFFSET ) = value;
-}
-
-
-byte chksum__32__calc_value( byte* data, long offset ) {
-
- int i;
- int len;
- byte sum;
-
- check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" );
- len = *( data + offset + _32__LEN ) << 4;
- check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" );
- sum = 0;
- for( i = 0; i < len; i++ ) {
- if( i != _32__CHKSUM ) {
- sum = sum + *( data + offset + i );
- }
- }
- sum = -sum;
- return( sum );
-}
-
-
-long chksum__32__get_offset( byte* data, long offset ) {
-
- long result = -1L;
-
- offset = offset + 0x0F;
- offset = offset & ~( 0x0F );
- while( offset + 16 < MAX_OFFSET ) {
- offset = offset + 16;
- if( *( data + offset + 0 ) == '_' && \
- *( data + offset + 1 ) == '3' && \
- *( data + offset + 2 ) == '2' && \
- *( data + offset + 3 ) == '_' ) {
- result = offset;
- break;
- }
- }
- return( result );
-}
-
-
-byte chksum__32__get_value( byte* data, long offset ) {
-
- check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
- return( *( data + offset + _32__CHKSUM ) );
-}
-
-
-void chksum__32__set_value( byte* data, long offset, byte value ) {
-
- check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
- *( data + offset + _32__CHKSUM ) = value;
-}
-
-
-byte chksum__mp__calc_value( byte* data, long offset ) {
-
- int i;
- int len;
- byte sum;
-
- check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" );
- len = *( data + offset + _MP__LEN ) << 4;
- check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" );
- sum = 0;
- for( i = 0; i < len; i++ ) {
- if( i != _MP__CHKSUM ) {
- sum = sum + *( data + offset + i );
- }
- }
- sum = -sum;
- return( sum );
-}
-
-
-long chksum__mp__get_offset( byte* data, long offset ) {
-
- long result = -1L;
-
- offset = offset + 0x0F;
- offset = offset & ~( 0x0F );
- while( offset + 16 < MAX_OFFSET ) {
- offset = offset + 16;
- if( *( data + offset + 0 ) == '_' && \
- *( data + offset + 1 ) == 'M' && \
- *( data + offset + 2 ) == 'P' && \
- *( data + offset + 3 ) == '_' ) {
- result = offset;
- break;
- }
- }
- return( result );
-}
-
-
-byte chksum__mp__get_value( byte* data, long offset ) {
-
- check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
- return( *( data + offset + _MP__CHKSUM ) );
-}
-
-
-void chksum__mp__set_value( byte* data, long offset, byte value ) {
-
- check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
- *( data + offset + _MP__CHKSUM ) = value;
-}
-
-
-byte chksum_pcmp_calc_value( byte* data, long offset ) {
-
- int i;
- int len;
- byte sum;
-
- check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" );
- len = *( data + offset + PCMP_BASELEN ) + \
- ( *( data + offset + PCMP_BASELEN + 1 ) << 8 );
- check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" );
- if( *( data + offset + PCMP_EXT_LEN ) | \
- *( data + offset + PCMP_EXT_LEN + 1 ) | \
- *( data + offset + PCMP_EXT_CHKSUM ) ) {
- check( 0, "PCMP header indicates extended tables (unsupported)" );
- }
- sum = 0;
- for( i = 0; i < len; i++ ) {
- if( i != PCMP_CHKSUM ) {
- sum = sum + *( data + offset + i );
- }
- }
- sum = -sum;
- return( sum );
-}
-
-
-long chksum_pcmp_get_offset( byte* data, long offset ) {
-
- long result = -1L;
-
- offset = offset + 0x0F;
- offset = offset & ~( 0x0F );
- while( offset + 16 < MAX_OFFSET ) {
- offset = offset + 16;
- if( *( data + offset + 0 ) == 'P' && \
- *( data + offset + 1 ) == 'C' && \
- *( data + offset + 2 ) == 'M' && \
- *( data + offset + 3 ) == 'P' ) {
- result = offset;
- break;
- }
- }
- return( result );
-}
-
-
-byte chksum_pcmp_get_value( byte* data, long offset ) {
-
- check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
- return( *( data + offset + PCMP_CHKSUM ) );
-}
-
-
-void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
-
- check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
- *( data + offset + PCMP_CHKSUM ) = value;
-}
-
-
-byte chksum__pir_calc_value( byte* data, long offset ) {
-
- int i;
- int len;
- byte sum;
-
- check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" );
- len = *( data + offset + _PIR_LEN ) + \
- ( *( data + offset + _PIR_LEN + 1 ) << 8 );
- check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" );
- sum = 0;
- for( i = 0; i < len; i++ ) {
- if( i != _PIR_CHKSUM ) {
- sum = sum + *( data + offset + i );
- }
- }
- sum = -sum;
- return( sum );
-}
-
-
-long chksum__pir_get_offset( byte* data, long offset ) {
-
- long result = -1L;
-
- offset = offset + 0x0F;
- offset = offset & ~( 0x0F );
- while( offset + 16 < MAX_OFFSET ) {
- offset = offset + 16;
- if( *( data + offset + 0 ) == '$' && \
- *( data + offset + 1 ) == 'P' && \
- *( data + offset + 2 ) == 'I' && \
- *( data + offset + 3 ) == 'R' ) {
- result = offset;
- break;
- }
- }
- return( result );
-}
-
-
-byte chksum__pir_get_value( byte* data, long offset ) {
-
- check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
- return( *( data + offset + _PIR_CHKSUM ) );
-}
-
-
-void chksum__pir_set_value( byte* data, long offset, byte value ) {
-
- check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
- *( data + offset + _PIR_CHKSUM ) = value;
-}
-
diff --git a/kvm/bios/makesym.perl b/kvm/bios/makesym.perl
deleted file mode 100755
index 631265404..000000000
--- a/kvm/bios/makesym.perl
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/perl
-#
-# $Id: makesym.perl,v 1.1 2002/11/24 22:45:40 bdenney Exp $
-#
-# Read output file from as86 (e.g. rombios.txt) and write out a symbol
-# table suitable for the Bochs debugger.
-#
-
-$WHERE_BEFORE_SYM_TABLE = 0;
-$WHERE_IN_SYM_TABLE = 1;
-$WHERE_AFTER_SYM_TABLE = 2;
-
-$where = $WHERE_BEFORE_SYM_TABLE;
-while (<STDIN>) {
- chop;
- if ($where == WHERE_BEFORE_SYM_TABLE && /^Symbols:/) {
- $where = $WHERE_IN_SYM_TABLE;
- } elsif ($where == $WHERE_IN_SYM_TABLE && /^$/) {
- $where = $WHERE_AFTER_SYM_TABLE;
- }
- if ($where == $WHERE_IN_SYM_TABLE) {
- @F = split (/\s+/);
- ($name[0], $junk, $addr[0], $junk, $name[1], $junk, $addr[1]) = @F;
- foreach $col (0,1) {
- next if length $addr[$col] < 1;
- $addr[$col] =~ tr/A-Z/a-z/;
- $addr[$col] = "000f" . $addr[$col];
- print "$addr[$col] $name[$col]\n";
- }
- }
-}
diff --git a/kvm/bios/notes b/kvm/bios/notes
deleted file mode 100644
index ae1073e98..000000000
--- a/kvm/bios/notes
+++ /dev/null
@@ -1,44 +0,0 @@
-####################
-# Read Disk Sector #
-####################
-
-System programming:
--------------------
-
-(Int 13h, ah=2)
-in 1f7 until BSY cleared
-out 1f2, AL # number of sectors
-out 1f3, cl (bits 0-5) # starting sector number
-out 1f4, ch # cylinder number bits 0..7, 0 based
-out 1f5, cl (bits 6,7) & dh (bits 6,7) # cyl, bits 8..9, 10..11
-out 1f6, dh (bits 0..3) --> bits 0..3 # head number
- dh (bits 4..5) --> ??? # head number
- dl (bit 0) --> bit 4 # drive number
-out 1f7, 0x20 # read sectors command normal
-
-
-
-Drive response:
----------------
-
-* drive sets the busy bit in Status Reg to 1
-* if command parameters are wrong:
- > drive sets the aborted-command bit in the Error register and
- error bit in the Status register to 1.
- > Drive also sets the busy bit in the Status register to 0.
- > Drive then generates an interrupt to the system.
-* else:
- > drive executes an implied seek to desired track and
- reads sectors into sector buffer
- > when sector buffer is filled and the data is ready to be
- transferred, the drive sets the data-request bit to 1, sets
- the busy bit to 0, and generates an interrupt.
- > on a single-sector transfer, after the system has transferred
- the data, the drive sets the data-request bit and the busy bit to 0.
- > on a multiple-sector transfer, after the system has transferred
- the first sector of data, the drive sets the data-request bit to 0,
- and the busy bit to 1. When each subsequent sector is ready to be
- transferred, the drive sets the data-request bit to 1, the busy bit to 0,
- and generates an interrupt. When the system has tranferred the last sector,
- the drive sets the data-request bit and busy bit to 0.
-
diff --git a/kvm/bios/rombios.c b/kvm/bios/rombios.c
deleted file mode 100644
index ba270a2ce..000000000
--- a/kvm/bios/rombios.c
+++ /dev/null
@@ -1,11456 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id: rombios.c,v 1.182 2007/08/01 17:09:51 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-// ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
-
-
-// ROM BIOS compatability entry points:
-// ===================================
-// $e05b ; POST Entry Point
-// $e2c3 ; NMI Handler Entry Point
-// $e3fe ; INT 13h Fixed Disk Services Entry Point
-// $e401 ; Fixed Disk Parameter Table
-// $e6f2 ; INT 19h Boot Load Service Entry Point
-// $e6f5 ; Configuration Data Table
-// $e729 ; Baud Rate Generator Table
-// $e739 ; INT 14h Serial Communications Service Entry Point
-// $e82e ; INT 16h Keyboard Service Entry Point
-// $e987 ; INT 09h Keyboard Service Entry Point
-// $ec59 ; INT 13h Diskette Service Entry Point
-// $ef57 ; INT 0Eh Diskette Hardware ISR Entry Point
-// $efc7 ; Diskette Controller Parameter Table
-// $efd2 ; INT 17h Printer Service Entry Point
-// $f045 ; INT 10 Functions 0-Fh Entry Point
-// $f065 ; INT 10h Video Support Service Entry Point
-// $f0a4 ; MDA/CGA Video Parameter Table (INT 1Dh)
-// $f841 ; INT 12h Memory Size Service Entry Point
-// $f84d ; INT 11h Equipment List Service Entry Point
-// $f859 ; INT 15h System Services Entry Point
-// $fa6e ; Character Font for 320x200 & 640x200 Graphics (lower 128 characters)
-// $fe6e ; INT 1Ah Time-of-day Service Entry Point
-// $fea5 ; INT 08h System Timer ISR Entry Point
-// $fef3 ; Initial Interrupt Vector Offsets Loaded by POST
-// $ff53 ; IRET Instruction for Dummy Interrupt Handler
-// $ff54 ; INT 05h Print Screen Service Entry Point
-// $fff0 ; Power-up Entry Point
-// $fff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
-// $fffe ; System Model ID
-
-// NOTES for ATA/ATAPI driver (cbbochs@free.fr)
-// Features
-// - supports up to 4 ATA interfaces
-// - device/geometry detection
-// - 16bits/32bits device access
-// - pchs/lba access
-// - datain/dataout/packet command support
-//
-// NOTES for El-Torito Boot (cbbochs@free.fr)
-// - CD-ROM booting is only available if ATA/ATAPI Driver is available
-// - Current code is only able to boot mono-session cds
-// - Current code can not boot and emulate a hard-disk
-// the bios will panic otherwise
-// - Current code also use memory in EBDA segement.
-// - I used cmos byte 0x3D to store extended information on boot-device
-// - Code has to be modified modified to handle multiple cdrom drives
-// - Here are the cdrom boot failure codes:
-// 1 : no atapi device found
-// 2 : no atapi cdrom found
-// 3 : can not read cd - BRVD
-// 4 : cd is not eltorito (BRVD)
-// 5 : cd is not eltorito (ISO TAG)
-// 6 : cd is not eltorito (ELTORITO TAG)
-// 7 : can not read cd - boot catalog
-// 8 : boot catalog : bad header
-// 9 : boot catalog : bad platform
-// 10 : boot catalog : bad signature
-// 11 : boot catalog : bootable flag not set
-// 12 : can not read cd - boot image
-//
-// ATA driver
-// - EBDA segment.
-// I used memory starting at 0x121 in the segment
-// - the translation policy is defined in cmos regs 0x39 & 0x3a
-//
-// TODO :
-//
-// int74
-// - needs to be reworked. Uses direct [bp] offsets. (?)
-//
-// int13:
-// - f04 (verify sectors) isn't complete (?)
-// - f02/03/04 should set current cyl,etc in BDA (?)
-// - rewrite int13_relocated & clean up int13 entry code
-//
-// NOTES:
-// - NMI access (bit7 of addr written to 70h)
-//
-// ATA driver
-// - should handle the "don't detect" bit (cmos regs 0x3b & 0x3c)
-// - could send the multiple-sector read/write commands
-//
-// El-Torito
-// - Emulate a Hard-disk (currently only diskette can be emulated) see "FIXME ElTorito Harddisk"
-// - Implement remaining int13_cdemu functions (as defined by El-Torito specs)
-// - cdrom drive is hardcoded to ide 0 device 1 in several places. see "FIXME ElTorito Hardcoded"
-// - int13 Fix DL when emulating a cd. In that case DL is decremented before calling real int13.
-// This is ok. But DL should be reincremented afterwards.
-// - Fix all "FIXME ElTorito Various"
-// - should be able to boot any cdrom instead of the first one
-//
-// BCC Bug: find a generic way to handle the bug of #asm after an "if" (fixed in 0.16.7)
-
-#include "rombios.h"
-
-#define DEBUG_ATA 0
-#define DEBUG_INT13_HD 0
-#define DEBUG_INT13_CD 0
-#define DEBUG_INT13_ET 0
-#define DEBUG_INT13_FL 0
-#define DEBUG_INT15 0
-#define DEBUG_INT16 0
-#define DEBUG_INT1A 0
-#define DEBUG_INT74 0
-#define DEBUG_APM 0
-
-#define BX_CPU 3
-#define BX_USE_PS2_MOUSE 1
-#define BX_CALL_INT15_4F 1
-#define BX_USE_EBDA 1
-#define BX_SUPPORT_FLOPPY 1
-#define BX_FLOPPY_ON_CNT 37 /* 2 seconds */
-#define BX_PCIBIOS 1
-#define BX_APM 1
-
-#define BX_USE_ATADRV 1
-#define BX_ELTORITO_BOOT 1
-
-#define BX_MAX_ATA_INTERFACES 4
-#define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2)
-
-#define BX_VIRTUAL_PORTS 1 /* normal output to Bochs ports */
-#define BX_DEBUG_SERIAL 0 /* output to COM1 */
-
- /* model byte 0xFC = AT */
-#define SYS_MODEL_ID 0xFC
-#define SYS_SUBMODEL_ID 0x00
-#define BIOS_REVISION 1
-#define BIOS_CONFIG_TABLE 0xe6f5
-
-#ifndef BIOS_BUILD_DATE
-# define BIOS_BUILD_DATE "06/23/99"
-#endif
-
- // 1K of base memory used for Extended Bios Data Area (EBDA)
- // EBDA is used for PS/2 mouse support, and IDE BIOS, etc.
-#define EBDA_SEG 0x9FC0
-#define EBDA_SIZE 1 // In KiB
-#define BASE_MEM_IN_K (640 - EBDA_SIZE)
-
-/* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
-#define IPL_SEG 0x9ff0
-#define IPL_TABLE_OFFSET 0x0000
-#define IPL_TABLE_ENTRIES 8
-#define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */
-#define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */
-#define IPL_BOOTFIRST_OFFSET 0x0084 /* u16: user selected device */
-#define IPL_SIZE 0xff
-#define IPL_TYPE_FLOPPY 0x01
-#define IPL_TYPE_HARDDISK 0x02
-#define IPL_TYPE_CDROM 0x03
-#define IPL_TYPE_BEV 0x80
-
- // Sanity Checks
-#if BX_USE_ATADRV && BX_CPU<3
-# error The ATA/ATAPI Driver can only to be used with a 386+ cpu
-#endif
-#if BX_USE_ATADRV && !BX_USE_EBDA
-# error ATA/ATAPI Driver can only be used if EBDA is available
-#endif
-#if BX_ELTORITO_BOOT && !BX_USE_ATADRV
-# error El-Torito Boot can only be use if ATA/ATAPI Driver is available
-#endif
-#if BX_PCIBIOS && BX_CPU<3
-# error PCI BIOS can only be used with 386+ cpu
-#endif
-#if BX_APM && BX_CPU<3
-# error APM BIOS can only be used with 386+ cpu
-#endif
-
-// define this if you want to make PCIBIOS working on a specific bridge only
-// undef enables PCIBIOS when at least one PCI device is found
-// i440FX is emulated by Bochs and QEMU
-#define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge
-
-// #20 is dec 20
-// #$20 is hex 20 = 32
-// #0x20 is hex 20 = 32
-// LDA #$20
-// JSR $E820
-// LDD .i,S
-// JSR $C682
-// mov al, #$20
-
-// all hex literals should be prefixed with '0x'
-// grep "#[0-9a-fA-F][0-9a-fA-F]" rombios.c
-// no mov SEG-REG, #value, must mov register into seg-reg
-// grep -i "mov[ ]*.s" rombios.c
-
-// This is for compiling with gcc2 and gcc3
-#define ASM_START #asm
-#define ASM_END #endasm
-
-ASM_START
-.rom
-
-.org 0x0000
-
-#if BX_CPU >= 3
-use16 386
-#else
-use16 286
-#endif
-
-MACRO HALT
- ;; the HALT macro is called with the line number of the HALT call.
- ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
- ;; to print a BX_PANIC message. This will normally halt the simulation
- ;; with a message such as "BIOS panic at rombios.c, line 4091".
- ;; However, users can choose to make panics non-fatal and continue.
-#if BX_VIRTUAL_PORTS
- mov dx,#PANIC_PORT
- mov ax,#?1
- out dx,ax
-#else
- mov dx,#0x80
- mov ax,#?1
- out dx,al
-#endif
-MEND
-
-MACRO JMP_AP
- db 0xea
- dw ?2
- dw ?1
-MEND
-
-MACRO SET_INT_VECTOR
- mov ax, ?3
- mov ?1*4, ax
- mov ax, ?2
- mov ?1*4+2, ax
-MEND
-
-ASM_END
-
-typedef unsigned char Bit8u;
-typedef unsigned short Bit16u;
-typedef unsigned short bx_bool;
-typedef unsigned long Bit32u;
-
-
- void memsetb(seg,offset,value,count);
- void memcpyb(dseg,doffset,sseg,soffset,count);
- void memcpyd(dseg,doffset,sseg,soffset,count);
-
- // memset of count bytes
- void
- memsetb(seg,offset,value,count)
- Bit16u seg;
- Bit16u offset;
- Bit16u value;
- Bit16u count;
- {
- ASM_START
- push bp
- mov bp, sp
-
- push ax
- push cx
- push es
- push di
-
- mov cx, 10[bp] ; count
- test cx, cx
- je memsetb_end
- mov ax, 4[bp] ; segment
- mov es, ax
- mov ax, 6[bp] ; offset
- mov di, ax
- mov al, 8[bp] ; value
- cld
- rep
- stosb
-
- memsetb_end:
- pop di
- pop es
- pop cx
- pop ax
-
- pop bp
- ASM_END
- }
-
- // memcpy of count bytes
- void
- memcpyb(dseg,doffset,sseg,soffset,count)
- Bit16u dseg;
- Bit16u doffset;
- Bit16u sseg;
- Bit16u soffset;
- Bit16u count;
- {
- ASM_START
- push bp
- mov bp, sp
-
- push ax
- push cx
- push es
- push di
- push ds
- push si
-
- mov cx, 12[bp] ; count
- test cx, cx
- je memcpyb_end
- mov ax, 4[bp] ; dsegment
- mov es, ax
- mov ax, 6[bp] ; doffset
- mov di, ax
- mov ax, 8[bp] ; ssegment
- mov ds, ax
- mov ax, 10[bp] ; soffset
- mov si, ax
- cld
- rep
- movsb
-
- memcpyb_end:
- pop si
- pop ds
- pop di
- pop es
- pop cx
- pop ax
-
- pop bp
- ASM_END
- }
-
- // memcpy of count dword
- void
- memcpyd(dseg,doffset,sseg,soffset,count)
- Bit16u dseg;
- Bit16u doffset;
- Bit16u sseg;
- Bit16u soffset;
- Bit16u count;
- {
- ASM_START
- push bp
- mov bp, sp
-
- push ax
- push cx
- push es
- push di
- push ds
- push si
-
- mov cx, 12[bp] ; count
- test cx, cx
- je memcpyd_end
- mov ax, 4[bp] ; dsegment
- mov es, ax
- mov ax, 6[bp] ; doffset
- mov di, ax
- mov ax, 8[bp] ; ssegment
- mov ds, ax
- mov ax, 10[bp] ; soffset
- mov si, ax
- cld
- rep
- movsd
-
- memcpyd_end:
- pop si
- pop ds
- pop di
- pop es
- pop cx
- pop ax
-
- pop bp
- ASM_END
- }
-
- // read_dword and write_dword functions
- static Bit32u read_dword();
- static void write_dword();
-
- Bit32u
- read_dword(seg, offset)
- Bit16u seg;
- Bit16u offset;
- {
- ASM_START
- push bp
- mov bp, sp
-
- push bx
- push ds
- mov ax, 4[bp] ; segment
- mov ds, ax
- mov bx, 6[bp] ; offset
- mov ax, [bx]
- add bx, #2
- mov dx, [bx]
- ;; ax = return value (word)
- ;; dx = return value (word)
- pop ds
- pop bx
-
- pop bp
- ASM_END
- }
-
- void
- write_dword(seg, offset, data)
- Bit16u seg;
- Bit16u offset;
- Bit32u data;
- {
- ASM_START
- push bp
- mov bp, sp
-
- push ax
- push bx
- push ds
- mov ax, 4[bp] ; segment
- mov ds, ax
- mov bx, 6[bp] ; offset
- mov ax, 8[bp] ; data word
- mov [bx], ax ; write data word
- add bx, #2
- mov ax, 10[bp] ; data word
- mov [bx], ax ; write data word
- pop ds
- pop bx
- pop ax
-
- pop bp
- ASM_END
- }
-
- // Bit32u (unsigned long) and long helper functions
- ASM_START
-
- ;; and function
- landl:
- landul:
- SEG SS
- and ax,[di]
- SEG SS
- and bx,2[di]
- ret
-
- ;; add function
- laddl:
- laddul:
- SEG SS
- add ax,[di]
- SEG SS
- adc bx,2[di]
- ret
-
- ;; cmp function
- lcmpl:
- lcmpul:
- and eax, #0x0000FFFF
- shl ebx, #16
- or eax, ebx
- shr ebx, #16
- SEG SS
- cmp eax, dword ptr [di]
- ret
-
- ;; sub function
- lsubl:
- lsubul:
- SEG SS
- sub ax,[di]
- SEG SS
- sbb bx,2[di]
- ret
-
- ;; mul function
- lmull:
- lmulul:
- and eax, #0x0000FFFF
- shl ebx, #16
- or eax, ebx
- SEG SS
- mul eax, dword ptr [di]
- mov ebx, eax
- shr ebx, #16
- ret
-
- ;; dec function
- ldecl:
- ldecul:
- SEG SS
- dec dword ptr [bx]
- ret
-
- ;; or function
- lorl:
- lorul:
- SEG SS
- or ax,[di]
- SEG SS
- or bx,2[di]
- ret
-
- ;; inc function
- lincl:
- lincul:
- SEG SS
- inc dword ptr [bx]
- ret
-
- ;; tst function
- ltstl:
- ltstul:
- and eax, #0x0000FFFF
- shl ebx, #16
- or eax, ebx
- shr ebx, #16
- test eax, eax
- ret
-
- ;; sr function
- lsrul:
- mov cx,di
- jcxz lsr_exit
- and eax, #0x0000FFFF
- shl ebx, #16
- or eax, ebx
- lsr_loop:
- shr eax, #1
- loop lsr_loop
- mov ebx, eax
- shr ebx, #16
- lsr_exit:
- ret
-
- ;; sl function
- lsll:
- lslul:
- mov cx,di
- jcxz lsl_exit
- and eax, #0x0000FFFF
- shl ebx, #16
- or eax, ebx
- lsl_loop:
- shl eax, #1
- loop lsl_loop
- mov ebx, eax
- shr ebx, #16
- lsl_exit:
- ret
-
- idiv_:
- cwd
- idiv bx
- ret
-
- idiv_u:
- xor dx,dx
- div bx
- ret
-
- ldivul:
- and eax, #0x0000FFFF
- shl ebx, #16
- or eax, ebx
- xor edx, edx
- SEG SS
- mov bx, 2[di]
- shl ebx, #16
- SEG SS
- mov bx, [di]
- div ebx
- mov ebx, eax
- shr ebx, #16
- ret
-
- ASM_END
-
-// for access to RAM area which is used by interrupt vectors
-// and BIOS Data Area
-
-typedef struct {
- unsigned char filler1[0x400];
- unsigned char filler2[0x6c];
- Bit16u ticks_low;
- Bit16u ticks_high;
- Bit8u midnight_flag;
- } bios_data_t;
-
-#define BiosData ((bios_data_t *) 0)
-
-#if BX_USE_ATADRV
- typedef struct {
- Bit16u heads; // # heads
- Bit16u cylinders; // # cylinders
- Bit16u spt; // # sectors / track
- } chs_t;
-
- // DPTE definition
- typedef struct {
- Bit16u iobase1;
- Bit16u iobase2;
- Bit8u prefix;
- Bit8u unused;
- Bit8u irq;
- Bit8u blkcount;
- Bit8u dma;
- Bit8u pio;
- Bit16u options;
- Bit16u reserved;
- Bit8u revision;
- Bit8u checksum;
- } dpte_t;
-
- typedef struct {
- Bit8u iface; // ISA or PCI
- Bit16u iobase1; // IO Base 1
- Bit16u iobase2; // IO Base 2
- Bit8u irq; // IRQ
- } ata_channel_t;
-
- typedef struct {
- Bit8u type; // Detected type of ata (ata/atapi/none/unknown)
- Bit8u device; // Detected type of attached devices (hd/cd/none)
- Bit8u removable; // Removable device flag
- Bit8u lock; // Locks for removable devices
- Bit8u mode; // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA
- Bit16u blksize; // block size
-
- Bit8u translation; // type of translation
- chs_t lchs; // Logical CHS
- chs_t pchs; // Physical CHS
-
- Bit32u sectors_low; // Total sectors count
- Bit32u sectors_high;
- } ata_device_t;
-
- typedef struct {
- // ATA channels info
- ata_channel_t channels[BX_MAX_ATA_INTERFACES];
-
- // ATA devices info
- ata_device_t devices[BX_MAX_ATA_DEVICES];
- //
- // map between (bios hd id - 0x80) and ata channels
- Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES];
-
- // map between (bios cd id - 0xE0) and ata channels
- Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES];
-
- // Buffer for DPTE table
- dpte_t dpte;
-
- // Count of transferred sectors and bytes
- Bit16u trsfsectors;
- Bit32u trsfbytes;
-
- } ata_t;
-
-#if BX_ELTORITO_BOOT
- // ElTorito Device Emulation data
- typedef struct {
- Bit8u active;
- Bit8u media;
- Bit8u emulated_drive;
- Bit8u controller_index;
- Bit16u device_spec;
- Bit32u ilba;
- Bit16u buffer_segment;
- Bit16u load_segment;
- Bit16u sector_count;
-
- // Virtual device
- chs_t vdevice;
- } cdemu_t;
-#endif // BX_ELTORITO_BOOT
-
- // for access to EBDA area
- // The EBDA structure should conform to
- // http://www.frontiernet.net/~fys/rombios.htm document
- // I made the ata and cdemu structs begin at 0x121 in the EBDA seg
- // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot
- // device tables are at IPL_SEG
- typedef struct {
- unsigned char filler1[0x3D];
-
- // FDPT - Can be splitted in data members if needed
- unsigned char fdpt0[0x10];
- unsigned char fdpt1[0x10];
-
- unsigned char filler2[0xC4];
-
- // ATA Driver data
- ata_t ata;
-
-#if BX_ELTORITO_BOOT
- // El Torito Emulation data
- cdemu_t cdemu;
-#endif // BX_ELTORITO_BOOT
-
- } ebda_data_t;
-
- #define EbdaData ((ebda_data_t *) 0)
-
- // for access to the int13ext structure
- typedef struct {
- Bit8u size;
- Bit8u reserved;
- Bit16u count;
- Bit16u offset;
- Bit16u segment;
- Bit32u lba1;
- Bit32u lba2;
- } int13ext_t;
-
- #define Int13Ext ((int13ext_t *) 0)
-
- // Disk Physical Table definition
- typedef struct {
- Bit16u size;
- Bit16u infos;
- Bit32u cylinders;
- Bit32u heads;
- Bit32u spt;
- Bit32u sector_count1;
- Bit32u sector_count2;
- Bit16u blksize;
- Bit16u dpte_offset;
- Bit16u dpte_segment;
- Bit16u key;
- Bit8u dpi_length;
- Bit8u reserved1;
- Bit16u reserved2;
- Bit8u host_bus[4];
- Bit8u iface_type[8];
- Bit8u iface_path[8];
- Bit8u device_path[8];
- Bit8u reserved3;
- Bit8u checksum;
- } dpt_t;
-
- #define Int13DPT ((dpt_t *) 0)
-
-#endif // BX_USE_ATADRV
-
-typedef struct {
- union {
- struct {
- Bit16u di, si, bp, sp;
- Bit16u bx, dx, cx, ax;
- } r16;
- struct {
- Bit16u filler[4];
- Bit8u bl, bh, dl, dh, cl, ch, al, ah;
- } r8;
- } u;
- } pusha_regs_t;
-
-typedef struct {
- union {
- struct {
- Bit32u edi, esi, ebp, esp;
- Bit32u ebx, edx, ecx, eax;
- } r32;
- struct {
- Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4;
- Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8;
- } r16;
- struct {
- Bit32u filler[4];
- Bit8u bl, bh;
- Bit16u filler1;
- Bit8u dl, dh;
- Bit16u filler2;
- Bit8u cl, ch;
- Bit16u filler3;
- Bit8u al, ah;
- Bit16u filler4;
- } r8;
- } u;
-} pushad_regs_t;
-
-typedef struct {
- union {
- struct {
- Bit16u flags;
- } r16;
- struct {
- Bit8u flagsl;
- Bit8u flagsh;
- } r8;
- } u;
- } flags_t;
-
-#define SetCF(x) x.u.r8.flagsl |= 0x01
-#define SetZF(x) x.u.r8.flagsl |= 0x40
-#define ClearCF(x) x.u.r8.flagsl &= 0xfe
-#define ClearZF(x) x.u.r8.flagsl &= 0xbf
-#define GetCF(x) (x.u.r8.flagsl & 0x01)
-
-typedef struct {
- Bit16u ip;
- Bit16u cs;
- flags_t flags;
- } iret_addr_t;
-
-typedef struct {
- Bit16u type;
- Bit16u flags;
- Bit32u vector;
- Bit32u description;
- Bit32u reserved;
- } ipl_entry_t;
-
-
-
-static Bit8u inb();
-static Bit8u inb_cmos();
-static void outb();
-static void outb_cmos();
-static Bit16u inw();
-static void outw();
-static void init_rtc();
-static bx_bool rtc_updating();
-
-static Bit8u read_byte();
-static Bit16u read_word();
-static void write_byte();
-static void write_word();
-static void bios_printf();
-
-static Bit8u inhibit_mouse_int_and_events();
-static void enable_mouse_int_and_events();
-static Bit8u send_to_mouse_ctrl();
-static Bit8u get_mouse_data();
-static void set_kbd_command_byte();
-
-static void int09_function();
-static void int13_harddisk();
-static void int13_cdrom();
-static void int13_cdemu();
-static void int13_eltorito();
-static void int13_diskette_function();
-static void int14_function();
-static void int15_function();
-static void int16_function();
-static void int17_function();
-static void int19_function();
-static void int1a_function();
-static void int70_function();
-static void int74_function();
-static Bit16u get_CS();
-static Bit16u get_SS();
-static unsigned int enqueue_key();
-static unsigned int dequeue_key();
-static void get_hd_geometry();
-static void set_diskette_ret_status();
-static void set_diskette_current_cyl();
-static void determine_floppy_media();
-static bx_bool floppy_drive_exists();
-static bx_bool floppy_drive_recal();
-static bx_bool floppy_media_known();
-static bx_bool floppy_media_sense();
-static bx_bool set_enable_a20();
-static void debugger_on();
-static void debugger_off();
-static void keyboard_init();
-static void keyboard_panic();
-static void shutdown_status_panic();
-static void nmi_handler_msg();
-static void delay_ticks();
-static void delay_ticks_and_check_for_keystroke();
-
-static void interactive_bootkey();
-static void print_bios_banner();
-static void print_boot_device();
-static void print_boot_failure();
-static void print_cdromboot_failure();
-
-# if BX_USE_ATADRV
-
-// ATA / ATAPI driver
-void ata_init();
-void ata_detect();
-void ata_reset();
-
-Bit16u ata_cmd_non_data();
-Bit16u ata_cmd_data_in();
-Bit16u ata_cmd_data_out();
-Bit16u ata_cmd_packet();
-
-Bit16u atapi_get_sense();
-Bit16u atapi_is_ready();
-Bit16u atapi_is_cdrom();
-
-#endif // BX_USE_ATADRV
-
-#if BX_ELTORITO_BOOT
-
-void cdemu_init();
-Bit8u cdemu_isactive();
-Bit8u cdemu_emulated_drive();
-
-Bit16u cdrom_boot();
-
-#endif // BX_ELTORITO_BOOT
-
-static char bios_cvs_version_string[] = "$Revision: 1.182 $ $Date: 2007/08/01 17:09:51 $";
-
-#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
-
-#if DEBUG_ATA
-# define BX_DEBUG_ATA(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_ATA(a...)
-#endif
-#if DEBUG_INT13_HD
-# define BX_DEBUG_INT13_HD(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT13_HD(a...)
-#endif
-#if DEBUG_INT13_CD
-# define BX_DEBUG_INT13_CD(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT13_CD(a...)
-#endif
-#if DEBUG_INT13_ET
-# define BX_DEBUG_INT13_ET(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT13_ET(a...)
-#endif
-#if DEBUG_INT13_FL
-# define BX_DEBUG_INT13_FL(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT13_FL(a...)
-#endif
-#if DEBUG_INT15
-# define BX_DEBUG_INT15(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT15(a...)
-#endif
-#if DEBUG_INT16
-# define BX_DEBUG_INT16(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT16(a...)
-#endif
-#if DEBUG_INT1A
-# define BX_DEBUG_INT1A(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT1A(a...)
-#endif
-#if DEBUG_INT74
-# define BX_DEBUG_INT74(a...) BX_DEBUG(a)
-#else
-# define BX_DEBUG_INT74(a...)
-#endif
-
-#define SET_AL(val8) AX = ((AX & 0xff00) | (val8))
-#define SET_BL(val8) BX = ((BX & 0xff00) | (val8))
-#define SET_CL(val8) CX = ((CX & 0xff00) | (val8))
-#define SET_DL(val8) DX = ((DX & 0xff00) | (val8))
-#define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8))
-#define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8))
-#define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8))
-#define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8))
-
-#define GET_AL() ( AX & 0x00ff )
-#define GET_BL() ( BX & 0x00ff )
-#define GET_CL() ( CX & 0x00ff )
-#define GET_DL() ( DX & 0x00ff )
-#define GET_AH() ( AX >> 8 )
-#define GET_BH() ( BX >> 8 )
-#define GET_CH() ( CX >> 8 )
-#define GET_DH() ( DX >> 8 )
-
-#define GET_ELDL() ( ELDX & 0x00ff )
-#define GET_ELDH() ( ELDX >> 8 )
-
-#define SET_CF() FLAGS |= 0x0001
-#define CLEAR_CF() FLAGS &= 0xfffe
-#define GET_CF() (FLAGS & 0x0001)
-
-#define SET_ZF() FLAGS |= 0x0040
-#define CLEAR_ZF() FLAGS &= 0xffbf
-#define GET_ZF() (FLAGS & 0x0040)
-
-#define UNSUPPORTED_FUNCTION 0x86
-
-#define none 0
-#define MAX_SCAN_CODE 0x58
-
-static struct {
- Bit16u normal;
- Bit16u shift;
- Bit16u control;
- Bit16u alt;
- Bit8u lock_flags;
- } scan_to_scanascii[MAX_SCAN_CODE + 1] = {
- { none, none, none, none, none },
- { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */
- { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */
- { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */
- { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */
- { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */
- { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */
- { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */
- { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */
- { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */
- { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */
- { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */
- { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */
- { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */
- { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */
- { 0x0f09, 0x0f00, none, none, none }, /* tab */
- { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 }, /* Q */
- { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 }, /* W */
- { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 }, /* E */
- { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 }, /* R */
- { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 }, /* T */
- { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 }, /* Y */
- { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 }, /* U */
- { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 }, /* I */
- { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 }, /* O */
- { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 }, /* P */
- { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */
- { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */
- { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */
- { none, none, none, none, none }, /* L Ctrl */
- { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 }, /* A */
- { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 }, /* S */
- { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 }, /* D */
- { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 }, /* F */
- { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 }, /* G */
- { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 }, /* H */
- { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 }, /* J */
- { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 }, /* K */
- { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 }, /* L */
- { 0x273b, 0x273a, none, none, none }, /* ;: */
- { 0x2827, 0x2822, none, none, none }, /* '" */
- { 0x2960, 0x297e, none, none, none }, /* `~ */
- { none, none, none, none, none }, /* L shift */
- { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */
- { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 }, /* Z */
- { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 }, /* X */
- { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 }, /* C */
- { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 }, /* V */
- { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 }, /* B */
- { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 }, /* N */
- { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 }, /* M */
- { 0x332c, 0x333c, none, none, none }, /* ,< */
- { 0x342e, 0x343e, none, none, none }, /* .> */
- { 0x352f, 0x353f, none, none, none }, /* /? */
- { none, none, none, none, none }, /* R Shift */
- { 0x372a, 0x372a, none, none, none }, /* * */
- { none, none, none, none, none }, /* L Alt */
- { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */
- { none, none, none, none, none }, /* caps lock */
- { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */
- { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */
- { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */
- { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */
- { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */
- { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */
- { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */
- { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */
- { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */
- { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */
- { none, none, none, none, none }, /* Num Lock */
- { none, none, none, none, none }, /* Scroll Lock */
- { 0x4700, 0x4737, 0x7700, none, 0x20 }, /* 7 Home */
- { 0x4800, 0x4838, none, none, 0x20 }, /* 8 UP */
- { 0x4900, 0x4939, 0x8400, none, 0x20 }, /* 9 PgUp */
- { 0x4a2d, 0x4a2d, none, none, none }, /* - */
- { 0x4b00, 0x4b34, 0x7300, none, 0x20 }, /* 4 Left */
- { 0x4c00, 0x4c35, none, none, 0x20 }, /* 5 */
- { 0x4d00, 0x4d36, 0x7400, none, 0x20 }, /* 6 Right */
- { 0x4e2b, 0x4e2b, none, none, none }, /* + */
- { 0x4f00, 0x4f31, 0x7500, none, 0x20 }, /* 1 End */
- { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */
- { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */
- { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */
- { 0x5300, 0x532e, none, none, 0x20 }, /* Del */
- { none, none, none, none, none },
- { none, none, none, none, none },
- { 0x565c, 0x567c, none, none, none }, /* \| */
- { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
- { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */
- };
-
- Bit8u
-inb(port)
- Bit16u port;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push dx
- mov dx, 4[bp]
- in al, dx
- pop dx
-
- pop bp
-ASM_END
-}
-
-#if BX_USE_ATADRV
- Bit16u
-inw(port)
- Bit16u port;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push dx
- mov dx, 4[bp]
- in ax, dx
- pop dx
-
- pop bp
-ASM_END
-}
-#endif
-
- void
-outb(port, val)
- Bit16u port;
- Bit8u val;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push ax
- push dx
- mov dx, 4[bp]
- mov al, 6[bp]
- out dx, al
- pop dx
- pop ax
-
- pop bp
-ASM_END
-}
-
-#if BX_USE_ATADRV
- void
-outw(port, val)
- Bit16u port;
- Bit16u val;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push ax
- push dx
- mov dx, 4[bp]
- mov ax, 6[bp]
- out dx, ax
- pop dx
- pop ax
-
- pop bp
-ASM_END
-}
-#endif
-
- void
-outb_cmos(cmos_reg, val)
- Bit8u cmos_reg;
- Bit8u val;
-{
-ASM_START
- push bp
- mov bp, sp
-
- mov al, 4[bp] ;; cmos_reg
- out 0x70, al
- mov al, 6[bp] ;; val
- out 0x71, al
-
- pop bp
-ASM_END
-}
-
- Bit8u
-inb_cmos(cmos_reg)
- Bit8u cmos_reg;
-{
-ASM_START
- push bp
- mov bp, sp
-
- mov al, 4[bp] ;; cmos_reg
- out 0x70, al
- in al, 0x71
-
- pop bp
-ASM_END
-}
-
- void
-init_rtc()
-{
- outb_cmos(0x0a, 0x26);
- outb_cmos(0x0b, 0x02);
- inb_cmos(0x0c);
- inb_cmos(0x0d);
-}
-
- bx_bool
-rtc_updating()
-{
- // This function checks to see if the update-in-progress bit
- // is set in CMOS Status Register A. If not, it returns 0.
- // If it is set, it tries to wait until there is a transition
- // to 0, and will return 0 if such a transition occurs. A 1
- // is returned only after timing out. The maximum period
- // that this bit should be set is constrained to 244useconds.
- // The count I use below guarantees coverage or more than
- // this time, with any reasonable IPS setting.
-
- Bit16u count;
-
- count = 25000;
- while (--count != 0) {
- if ( (inb_cmos(0x0a) & 0x80) == 0 )
- return(0);
- }
- return(1); // update-in-progress never transitioned to 0
-}
-
-
- Bit8u
-read_byte(seg, offset)
- Bit16u seg;
- Bit16u offset;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push bx
- push ds
- mov ax, 4[bp] ; segment
- mov ds, ax
- mov bx, 6[bp] ; offset
- mov al, [bx]
- ;; al = return value (byte)
- pop ds
- pop bx
-
- pop bp
-ASM_END
-}
-
- Bit16u
-read_word(seg, offset)
- Bit16u seg;
- Bit16u offset;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push bx
- push ds
- mov ax, 4[bp] ; segment
- mov ds, ax
- mov bx, 6[bp] ; offset
- mov ax, [bx]
- ;; ax = return value (word)
- pop ds
- pop bx
-
- pop bp
-ASM_END
-}
-
- void
-write_byte(seg, offset, data)
- Bit16u seg;
- Bit16u offset;
- Bit8u data;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push ax
- push bx
- push ds
- mov ax, 4[bp] ; segment
- mov ds, ax
- mov bx, 6[bp] ; offset
- mov al, 8[bp] ; data byte
- mov [bx], al ; write data byte
- pop ds
- pop bx
- pop ax
-
- pop bp
-ASM_END
-}
-
- void
-write_word(seg, offset, data)
- Bit16u seg;
- Bit16u offset;
- Bit16u data;
-{
-ASM_START
- push bp
- mov bp, sp
-
- push ax
- push bx
- push ds
- mov ax, 4[bp] ; segment
- mov ds, ax
- mov bx, 6[bp] ; offset
- mov ax, 8[bp] ; data word
- mov [bx], ax ; write data word
- pop ds
- pop bx
- pop ax
-
- pop bp
-ASM_END
-}
-
- Bit16u
-get_CS()
-{
-ASM_START
- mov ax, cs
-ASM_END
-}
-
- Bit16u
-get_SS()
-{
-ASM_START
- mov ax, ss
-ASM_END
-}
-
-#if BX_DEBUG_SERIAL
-/* serial debug port*/
-#define BX_DEBUG_PORT 0x03f8
-
-/* data */
-#define UART_RBR 0x00
-#define UART_THR 0x00
-
-/* control */
-#define UART_IER 0x01
-#define UART_IIR 0x02
-#define UART_FCR 0x02
-#define UART_LCR 0x03
-#define UART_MCR 0x04
-#define UART_DLL 0x00
-#define UART_DLM 0x01
-
-/* status */
-#define UART_LSR 0x05
-#define UART_MSR 0x06
-#define UART_SCR 0x07
-
-int uart_can_tx_byte(base_port)
- Bit16u base_port;
-{
- return inb(base_port + UART_LSR) & 0x20;
-}
-
-void uart_wait_to_tx_byte(base_port)
- Bit16u base_port;
-{
- while (!uart_can_tx_byte(base_port));
-}
-
-void uart_wait_until_sent(base_port)
- Bit16u base_port;
-{
- while (!(inb(base_port + UART_LSR) & 0x40));
-}
-
-void uart_tx_byte(base_port, data)
- Bit16u base_port;
- Bit8u data;
-{
- uart_wait_to_tx_byte(base_port);
- outb(base_port + UART_THR, data);
- uart_wait_until_sent(base_port);
-}
-#endif
-
- void
-wrch(c)
- Bit8u c;
-{
- ASM_START
- push bp
- mov bp, sp
-
- push bx
- mov ah, #0x0e
- mov al, 4[bp]
- xor bx,bx
- int #0x10
- pop bx
-
- pop bp
- ASM_END
-}
-
- void
-send(action, c)
- Bit16u action;
- Bit8u c;
-{
-#if BX_DEBUG_SERIAL
- if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
- uart_tx_byte(BX_DEBUG_PORT, c);
-#endif
-#if BX_VIRTUAL_PORTS
- if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c);
- if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);
-#endif
- if (action & BIOS_PRINTF_SCREEN) {
- if (c == '\n') wrch('\r');
- wrch(c);
- }
-}
-
- void
-put_int(action, val, width, neg)
- Bit16u action;
- short val, width;
- bx_bool neg;
-{
- short nval = val / 10;
- if (nval)
- put_int(action, nval, width - 1, neg);
- else {
- while (--width > 0) send(action, ' ');
- if (neg) send(action, '-');
- }
- send(action, val - (nval * 10) + '0');
-}
-
- void
-put_uint(action, val, width, neg)
- Bit16u action;
- unsigned short val;
- short width;
- bx_bool neg;
-{
- unsigned short nval = val / 10;
- if (nval)
- put_uint(action, nval, width - 1, neg);
- else {
- while (--width > 0) send(action, ' ');
- if (neg) send(action, '-');
- }
- send(action, val - (nval * 10) + '0');
-}
-
- void
-put_luint(action, val, width, neg)
- Bit16u action;
- unsigned long val;
- short width;
- bx_bool neg;
-{
- unsigned long nval = val / 10;
- if (nval)
- put_luint(action, nval, width - 1, neg);
- else {
- while (--width > 0) send(action, ' ');
- if (neg) send(action, '-');
- }
- send(action, val - (nval * 10) + '0');
-}
-
-void put_str(action, segment, offset)
- Bit16u action;
- Bit16u segment;
- Bit16u offset;
-{
- Bit8u c;
-
- while (c = read_byte(segment, offset)) {
- send(action, c);
- offset++;
- }
-}
-
- void
-delay_ticks(ticks)
- Bit16u ticks;
-{
- long ticks_to_wait, delta;
- Bit32u prev_ticks, t;
-
- /*
- * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
- * We also have to be careful about interrupt storms.
- */
-ASM_START
- pushf
- sti
-ASM_END
- ticks_to_wait = ticks;
- prev_ticks = read_dword(0x0, 0x46c);
- do
- {
-ASM_START
- hlt
-ASM_END
- t = read_dword(0x0, 0x46c);
- if (t > prev_ticks)
- {
- delta = t - prev_ticks; /* The temp var is required or bcc screws up. */
- ticks_to_wait -= delta;
- }
- else if (t < prev_ticks)
- {
- ticks_to_wait -= t; /* wrapped */
- }
-
- prev_ticks = t;
- } while (ticks_to_wait > 0);
-ASM_START
- cli
- popf
-ASM_END
-}
-
- Bit8u
-check_for_keystroke()
-{
-ASM_START
- mov ax, #0x100
- int #0x16
- jz no_key
- mov al, #1
- jmp done
-no_key:
- xor al, al
-done:
-ASM_END
-}
-
- Bit8u
-get_keystroke()
-{
-ASM_START
- mov ax, #0x0
- int #0x16
- xchg ah, al
-ASM_END
-}
-
- void
-delay_ticks_and_check_for_keystroke(ticks, count)
- Bit16u ticks, count;
-{
- Bit16u i;
- for (i = 1; i <= count; i++) {
- delay_ticks(ticks);
- if (check_for_keystroke())
- break;
- }
-}
-
-//--------------------------------------------------------------------------
-// bios_printf()
-// A compact variable argument printf function.
-//
-// Supports %[format_width][length]format
-// where format can be x,X,u,d,s,S,c
-// and the optional length modifier is l (ell)
-//--------------------------------------------------------------------------
- void
-bios_printf(action, s)
- Bit16u action;
- Bit8u *s;
-{
- Bit8u c, format_char;
- bx_bool in_format;
- short i;
- Bit16u *arg_ptr;
- Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd;
-
- arg_ptr = &s;
- arg_seg = get_SS();
-
- in_format = 0;
- format_width = 0;
-
- if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) {
-#if BX_VIRTUAL_PORTS
- outb(PANIC_PORT2, 0x00);
-#endif
- bios_printf (BIOS_PRINTF_SCREEN, "FATAL: ");
- }
-
- while (c = read_byte(get_CS(), s)) {
- if ( c == '%' ) {
- in_format = 1;
- format_width = 0;
- }
- else if (in_format) {
- if ( (c>='0') && (c<='9') ) {
- format_width = (format_width * 10) + (c - '0');
- }
- else {
- arg_ptr++; // increment to next arg
- arg = read_word(arg_seg, arg_ptr);
- if (c == 'x' || c == 'X') {
- if (format_width == 0)
- format_width = 4;
- if (c == 'x')
- hexadd = 'a';
- else
- hexadd = 'A';
- for (i=format_width-1; i>=0; i--) {
- nibble = (arg >> (4 * i)) & 0x000f;
- send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
- }
- }
- else if (c == 'u') {
- put_uint(action, arg, format_width, 0);
- }
- else if (c == 'l') {
- s++;
- c = read_byte(get_CS(), s); /* is it ld,lx,lu? */
- arg_ptr++; /* increment to next arg */
- hibyte = read_word(arg_seg, arg_ptr);
- if (c == 'd') {
- if (hibyte & 0x8000)
- put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1);
- else
- put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
- }
- else if (c == 'u') {
- put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
- }
- else if (c == 'x' || c == 'X')
- {
- if (format_width == 0)
- format_width = 8;
- if (c == 'x')
- hexadd = 'a';
- else
- hexadd = 'A';
- for (i=format_width-1; i>=0; i--) {
- nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f;
- send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
- }
- }
- }
- else if (c == 'd') {
- if (arg & 0x8000)
- put_int(action, -arg, format_width - 1, 1);
- else
- put_int(action, arg, format_width, 0);
- }
- else if (c == 's') {
- put_str(action, get_CS(), arg);
- }
- else if (c == 'S') {
- hibyte = arg;
- arg_ptr++;
- arg = read_word(arg_seg, arg_ptr);
- put_str(action, hibyte, arg);
- }
- else if (c == 'c') {
- send(action, arg);
- }
- else
- BX_PANIC("bios_printf: unknown format\n");
- in_format = 0;
- }
- }
- else {
- send(action, c);
- }
- s ++;
- }
-
- if (action & BIOS_PRINTF_HALT) {
- // freeze in a busy loop.
-ASM_START
- cli
- halt2_loop:
- hlt
- jmp halt2_loop
-ASM_END
- }
-}
-
-//--------------------------------------------------------------------------
-// keyboard_init
-//--------------------------------------------------------------------------
-// this file is based on LinuxBIOS implementation of keyboard.c
-// could convert to #asm to gain space
- void
-keyboard_init()
-{
- Bit16u max;
-
- /* ------------------- Flush buffers ------------------------*/
- /* Wait until buffer is empty */
- max=0xffff;
- while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
-
- /* flush incoming keys */
- max=0x2000;
- while (--max > 0) {
- outb(0x80, 0x00);
- if (inb(0x64) & 0x01) {
- inb(0x60);
- max = 0x2000;
- }
- }
-
- // Due to timer issues, and if the IPS setting is > 15000000,
- // the incoming keys might not be flushed here. That will
- // cause a panic a few lines below. See sourceforge bug report :
- // [ 642031 ] FATAL: Keyboard RESET error:993
-
- /* ------------------- controller side ----------------------*/
- /* send cmd = 0xAA, self test 8042 */
- outb(0x64, 0xaa);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
- if (max==0x0) keyboard_panic(00);
-
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01);
- if (max==0x0) keyboard_panic(01);
-
- /* read self-test result, 0x55 should be returned from 0x60 */
- if ((inb(0x60) != 0x55)){
- keyboard_panic(991);
- }
-
- /* send cmd = 0xAB, keyboard interface test */
- outb(0x64,0xab);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10);
- if (max==0x0) keyboard_panic(10);
-
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11);
- if (max==0x0) keyboard_panic(11);
-
- /* read keyboard interface test result, */
- /* 0x00 should be returned form 0x60 */
- if ((inb(0x60) != 0x00)) {
- keyboard_panic(992);
- }
-
- /* Enable Keyboard clock */
- outb(0x64,0xae);
- outb(0x64,0xa8);
-
- /* ------------------- keyboard side ------------------------*/
- /* reset kerboard and self test (keyboard side) */
- outb(0x60, 0xff);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20);
- if (max==0x0) keyboard_panic(20);
-
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21);
- if (max==0x0) keyboard_panic(21);
-
- /* keyboard should return ACK */
- if ((inb(0x60) != 0xfa)) {
- keyboard_panic(993);
- }
-
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x31);
- if (max==0x0) keyboard_panic(31);
-
- if ((inb(0x60) != 0xaa)) {
- keyboard_panic(994);
- }
-
- /* Disable keyboard */
- outb(0x60, 0xf5);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40);
- if (max==0x0) keyboard_panic(40);
-
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41);
- if (max==0x0) keyboard_panic(41);
-
- /* keyboard should return ACK */
- if ((inb(0x60) != 0xfa)) {
- keyboard_panic(995);
- }
-
- /* Write Keyboard Mode */
- outb(0x64, 0x60);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50);
- if (max==0x0) keyboard_panic(50);
-
- /* send cmd: scan code convert, disable mouse, enable IRQ 1 */
- outb(0x60, 0x61);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60);
- if (max==0x0) keyboard_panic(60);
-
- /* Enable keyboard */
- outb(0x60, 0xf4);
-
- /* Wait until buffer is empty */
- max=0xffff;
- while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70);
- if (max==0x0) keyboard_panic(70);
-
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71);
- if (max==0x0) keyboard_panic(70);
-
- /* keyboard should return ACK */
- if ((inb(0x60) != 0xfa)) {
- keyboard_panic(996);
- }
-
- outb(0x80, 0x77);
-}
-
-//--------------------------------------------------------------------------
-// keyboard_panic
-//--------------------------------------------------------------------------
- void
-keyboard_panic(status)
- Bit16u status;
-{
- // If you're getting a 993 keyboard panic here,
- // please see the comment in keyboard_init
-
- BX_PANIC("Keyboard error:%u\n",status);
-}
-
-//--------------------------------------------------------------------------
-// shutdown_status_panic
-// called when the shutdown statsu is not implemented, displays the status
-//--------------------------------------------------------------------------
- void
-shutdown_status_panic(status)
- Bit16u status;
-{
- BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
-}
-
-void s3_resume_panic()
-{
- BX_PANIC("Returned from s3_resume.\n");
-}
-
-//--------------------------------------------------------------------------
-// print_bios_banner
-// displays a the bios version
-//--------------------------------------------------------------------------
-void
-print_bios_banner()
-{
- printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
- BIOS_BUILD_DATE, bios_cvs_version_string);
- printf(
-#if BX_APM
- "apmbios "
-#endif
-#if BX_PCIBIOS
- "pcibios "
-#endif
-#if BX_ELTORITO_BOOT
- "eltorito "
-#endif
-#if BX_ROMBIOS32
- "rombios32 "
-#endif
- "\n\n");
-}
-
-//--------------------------------------------------------------------------
-// BIOS Boot Specification 1.0.1 compatibility
-//
-// Very basic support for the BIOS Boot Specification, which allows expansion
-// ROMs to register themselves as boot devices, instead of just stealing the
-// INT 19h boot vector.
-//
-// This is a hack: to do it properly requires a proper PnP BIOS and we aren't
-// one; we just lie to the option ROMs to make them behave correctly.
-// We also don't support letting option ROMs register as bootable disk
-// drives (BCVs), only as bootable devices (BEVs).
-//
-// http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
-//--------------------------------------------------------------------------
-
-static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
-
-static void
-init_boot_vectors()
-{
- ipl_entry_t e;
- Bit16u count = 0;
- Bit16u ss = get_SS();
-
- /* Clear out the IPL table. */
- memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, IPL_SIZE);
-
- /* User selected device not set */
- write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF);
-
- /* Floppy drive */
- e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
- memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
- count++;
-
- /* First HDD */
- e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
- memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
- count++;
-
-#if BX_ELTORITO_BOOT
- /* CDROM */
- e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
- memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
- count++;
-#endif
-
- /* Remember how many devices we have */
- write_word(IPL_SEG, IPL_COUNT_OFFSET, count);
- /* Not tried booting anything yet */
- write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
-}
-
-static Bit8u
-get_boot_vector(i, e)
-Bit16u i; ipl_entry_t *e;
-{
- Bit16u count;
- Bit16u ss = get_SS();
- /* Get the count of boot devices, and refuse to overrun the array */
- count = read_word(IPL_SEG, IPL_COUNT_OFFSET);
- if (i >= count) return 0;
- /* OK to read this device */
- memcpyb(ss, e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e));
- return 1;
-}
-
-#if BX_ELTORITO_BOOT
-#ifdef BX_QEMU
-int
-qemu_cfg_probe_bootkey()
-{
- outw(QEMU_CFG_CTL_PORT, QEMU_CFG_SIGNATURE);
- if (inb(QEMU_CFG_DATA_PORT) != 'Q' ||
- inb(QEMU_CFG_DATA_PORT) != 'E' ||
- inb(QEMU_CFG_DATA_PORT) != 'M' ||
- inb(QEMU_CFG_DATA_PORT) != 'U') return 1;
-
- outw(QEMU_CFG_CTL_PORT, QEMU_CFG_BOOT_MENU);
- return inb(QEMU_CFG_DATA_PORT);
-}
-#endif // BX_QEMU
-
- void
-interactive_bootkey()
-{
- ipl_entry_t e;
- Bit16u count;
- char description[33];
- Bit8u scan_code;
- Bit8u i;
- Bit16u ss = get_SS();
- Bit16u valid_choice = 0;
-
-#ifdef BX_QEMU
- if (!qemu_cfg_probe_bootkey()) return;
-#endif
-
- while (check_for_keystroke())
- get_keystroke();
-
- printf("Press F12 for boot menu.\n\n");
-
- delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
- if (check_for_keystroke())
- {
- scan_code = get_keystroke();
- if (scan_code == 0x86) /* F12 */
- {
- while (check_for_keystroke())
- get_keystroke();
-
- printf("Select boot device:\n\n");
-
- count = read_word(IPL_SEG, IPL_COUNT_OFFSET);
- for (i = 0; i < count; i++)
- {
- memcpyb(ss, &e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e));
- printf("%d. ", i+1);
- switch(e.type)
- {
- case IPL_TYPE_FLOPPY:
- case IPL_TYPE_HARDDISK:
- case IPL_TYPE_CDROM:
- printf("%s\n", drivetypes[e.type]);
- break;
- case IPL_TYPE_BEV:
- printf("%s", drivetypes[4]);
- if (e.description != 0)
- {
- memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32);
- description[32] = 0;
- printf(" [%S]", ss, description);
- }
- printf("\n");
- break;
- }
- }
-
- count++;
- while (!valid_choice) {
- scan_code = get_keystroke();
- if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
- {
- valid_choice = 1;
- }
- else if (scan_code <= count)
- {
- valid_choice = 1;
- scan_code -= 1;
- /* Set user selected device */
- write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code);
- }
- }
- printf("\n");
- }
- }
-}
-#endif // BX_ELTORITO_BOOT
-
-//--------------------------------------------------------------------------
-// print_boot_device
-// displays the boot device
-//--------------------------------------------------------------------------
-
-void
-print_boot_device(e)
- ipl_entry_t *e;
-{
- Bit16u type;
- char description[33];
- Bit16u ss = get_SS();
- type = e->type;
- /* NIC appears as type 0x80 */
- if (type == IPL_TYPE_BEV) type = 0x4;
- if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
- printf("Booting from %s", drivetypes[type]);
- /* print product string if BEV */
- if (type == 4 && e->description != 0) {
- /* first 32 bytes are significant */
- memcpyb(ss, &description, (Bit16u)(e->description >> 16), (Bit16u)(e->description & 0xffff), 32);
- /* terminate string */
- description[32] = 0;
- printf(" [%S]", ss, description);
- }
- printf("...\n");
-}
-
-//--------------------------------------------------------------------------
-// print_boot_failure
-// displays the reason why boot failed
-//--------------------------------------------------------------------------
- void
-print_boot_failure(type, reason)
- Bit16u type; Bit8u reason;
-{
- if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
-
- printf("Boot failed");
- if (type < 4) {
- /* Report the reason too */
- if (reason==0)
- printf(": not a bootable disk");
- else
- printf(": could not read the boot disk");
- }
- printf("\n\n");
-}
-
-//--------------------------------------------------------------------------
-// print_cdromboot_failure
-// displays the reason why boot failed
-//--------------------------------------------------------------------------
- void
-print_cdromboot_failure( code )
- Bit16u code;
-{
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code);
-
- return;
-}
-
-void
-nmi_handler_msg()
-{
- BX_PANIC("NMI Handler called\n");
-}
-
-void
-int18_panic_msg()
-{
- BX_PANIC("INT18: BOOT FAILURE\n");
-}
-
-void
-log_bios_start()
-{
-#if BX_DEBUG_SERIAL
- outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */
-#endif
- BX_INFO("%s\n", bios_cvs_version_string);
-}
-
- bx_bool
-set_enable_a20(val)
- bx_bool val;
-{
- Bit8u oldval;
-
- // Use PS2 System Control port A to set A20 enable
-
- // get current setting first
- oldval = inb(0x92);
-
- // change A20 status
- if (val)
- outb(0x92, oldval | 0x02);
- else
- outb(0x92, oldval & 0xfd);
-
- return((oldval & 0x02) != 0);
-}
-
- void
-debugger_on()
-{
- outb(0xfedc, 0x01);
-}
-
- void
-debugger_off()
-{
- outb(0xfedc, 0x00);
-}
-
-int
-s3_resume()
-{
- Bit32u s3_wakeup_vector;
- Bit8u s3_resume_flag;
-
- s3_resume_flag = read_byte(0x40, 0xb0);
- s3_wakeup_vector = read_dword(0x40, 0xb2);
-
- BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector);
- if (s3_resume_flag != 0xFE || !s3_wakeup_vector)
- return 0;
-
- write_byte(0x40, 0xb0, 0);
-
- /* setup wakeup vector */
- write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */
- write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */
-
- BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4),
- (s3_wakeup_vector & 0xF));
-ASM_START
- mov sp, #0 ;; disable tpr patching on boot CPU
- jmpf [0x04b6]
-ASM_END
- return 1;
-}
-
-#if BX_USE_ATADRV
-
-// ---------------------------------------------------------------------------
-// Start of ATA/ATAPI Driver
-// ---------------------------------------------------------------------------
-
-// Global defines -- ATA register and register bits.
-// command block & control block regs
-#define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0
-#define ATA_CB_ERR 1 // error in pio_base_addr1+1
-#define ATA_CB_FR 1 // feature reg out pio_base_addr1+1
-#define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2
-#define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3
-#define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4
-#define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5
-#define ATA_CB_DH 6 // device head in/out pio_base_addr1+6
-#define ATA_CB_STAT 7 // primary status in pio_base_addr1+7
-#define ATA_CB_CMD 7 // command out pio_base_addr1+7
-#define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6
-#define ATA_CB_DC 6 // device control out pio_base_addr2+6
-#define ATA_CB_DA 7 // device address in pio_base_addr2+7
-
-#define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
-#define ATA_CB_ER_BBK 0x80 // ATA bad block
-#define ATA_CB_ER_UNC 0x40 // ATA uncorrected error
-#define ATA_CB_ER_MC 0x20 // ATA media change
-#define ATA_CB_ER_IDNF 0x10 // ATA id not found
-#define ATA_CB_ER_MCR 0x08 // ATA media change request
-#define ATA_CB_ER_ABRT 0x04 // ATA command aborted
-#define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found
-#define ATA_CB_ER_NDAM 0x01 // ATA address mark not found
-
-#define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask)
-#define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request
-#define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort
-#define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media
-#define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication
-
-// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
-#define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask)
-#define ATA_CB_SC_P_REL 0x04 // ATAPI release
-#define ATA_CB_SC_P_IO 0x02 // ATAPI I/O
-#define ATA_CB_SC_P_CD 0x01 // ATAPI C/D
-
-// bits 7-4 of the device/head (CB_DH) reg
-#define ATA_CB_DH_DEV0 0xa0 // select device 0
-#define ATA_CB_DH_DEV1 0xb0 // select device 1
-#define ATA_CB_DH_LBA 0x40 // use LBA
-
-// status reg (CB_STAT and CB_ASTAT) bits
-#define ATA_CB_STAT_BSY 0x80 // busy
-#define ATA_CB_STAT_RDY 0x40 // ready
-#define ATA_CB_STAT_DF 0x20 // device fault
-#define ATA_CB_STAT_WFT 0x20 // write fault (old name)
-#define ATA_CB_STAT_SKC 0x10 // seek complete
-#define ATA_CB_STAT_SERV 0x10 // service
-#define ATA_CB_STAT_DRQ 0x08 // data request
-#define ATA_CB_STAT_CORR 0x04 // corrected
-#define ATA_CB_STAT_IDX 0x02 // index
-#define ATA_CB_STAT_ERR 0x01 // error (ATA)
-#define ATA_CB_STAT_CHK 0x01 // check (ATAPI)
-
-// device control reg (CB_DC) bits
-#define ATA_CB_DC_HD15 0x08 // bit should always be set to one
-#define ATA_CB_DC_SRST 0x04 // soft reset
-#define ATA_CB_DC_NIEN 0x02 // disable interrupts
-
-// Most mandtory and optional ATA commands (from ATA-3),
-#define ATA_CMD_CFA_ERASE_SECTORS 0xC0
-#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
-#define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87
-#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
-#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
-#define ATA_CMD_CHECK_POWER_MODE1 0xE5
-#define ATA_CMD_CHECK_POWER_MODE2 0x98
-#define ATA_CMD_DEVICE_RESET 0x08
-#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
-#define ATA_CMD_FLUSH_CACHE 0xE7
-#define ATA_CMD_FORMAT_TRACK 0x50
-#define ATA_CMD_IDENTIFY_DEVICE 0xEC
-#define ATA_CMD_IDENTIFY_DEVICE_PACKET 0xA1
-#define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1
-#define ATA_CMD_IDLE1 0xE3
-#define ATA_CMD_IDLE2 0x97
-#define ATA_CMD_IDLE_IMMEDIATE1 0xE1
-#define ATA_CMD_IDLE_IMMEDIATE2 0x95
-#define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
-#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
-#define ATA_CMD_NOP 0x00
-#define ATA_CMD_PACKET 0xA0
-#define ATA_CMD_READ_BUFFER 0xE4
-#define ATA_CMD_READ_DMA 0xC8
-#define ATA_CMD_READ_DMA_QUEUED 0xC7
-#define ATA_CMD_READ_MULTIPLE 0xC4
-#define ATA_CMD_READ_SECTORS 0x20
-#define ATA_CMD_READ_VERIFY_SECTORS 0x40
-#define ATA_CMD_RECALIBRATE 0x10
-#define ATA_CMD_REQUEST_SENSE 0x03
-#define ATA_CMD_SEEK 0x70
-#define ATA_CMD_SET_FEATURES 0xEF
-#define ATA_CMD_SET_MULTIPLE_MODE 0xC6
-#define ATA_CMD_SLEEP1 0xE6
-#define ATA_CMD_SLEEP2 0x99
-#define ATA_CMD_STANDBY1 0xE2
-#define ATA_CMD_STANDBY2 0x96
-#define ATA_CMD_STANDBY_IMMEDIATE1 0xE0
-#define ATA_CMD_STANDBY_IMMEDIATE2 0x94
-#define ATA_CMD_WRITE_BUFFER 0xE8
-#define ATA_CMD_WRITE_DMA 0xCA
-#define ATA_CMD_WRITE_DMA_QUEUED 0xCC
-#define ATA_CMD_WRITE_MULTIPLE 0xC5
-#define ATA_CMD_WRITE_SECTORS 0x30
-#define ATA_CMD_WRITE_VERIFY 0x3C
-
-#define ATA_IFACE_NONE 0x00
-#define ATA_IFACE_ISA 0x00
-#define ATA_IFACE_PCI 0x01
-
-#define ATA_TYPE_NONE 0x00
-#define ATA_TYPE_UNKNOWN 0x01
-#define ATA_TYPE_ATA 0x02
-#define ATA_TYPE_ATAPI 0x03
-
-#define ATA_DEVICE_NONE 0x00
-#define ATA_DEVICE_HD 0xFF
-#define ATA_DEVICE_CDROM 0x05
-
-#define ATA_MODE_NONE 0x00
-#define ATA_MODE_PIO16 0x00
-#define ATA_MODE_PIO32 0x01
-#define ATA_MODE_ISADMA 0x02
-#define ATA_MODE_PCIDMA 0x03
-#define ATA_MODE_USEIRQ 0x10
-
-#define ATA_TRANSLATION_NONE 0
-#define ATA_TRANSLATION_LBA 1
-#define ATA_TRANSLATION_LARGE 2
-#define ATA_TRANSLATION_RECHS 3
-
-#define ATA_DATA_NO 0x00
-#define ATA_DATA_IN 0x01
-#define ATA_DATA_OUT 0x02
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : initialization
-// ---------------------------------------------------------------------------
-void ata_init( )
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u channel, device;
-
- // Channels info init.
- for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
- write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE);
- write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0);
- write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2,0x0);
- write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
- }
-
- // Devices info init.
- for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
- write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].removable,0);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].lock,0);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_NONE);
- write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,0);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].translation,ATA_TRANSLATION_NONE);
- write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads,0);
- write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders,0);
- write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt,0);
- write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0);
- write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
- write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
-
- write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
- write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
- }
-
- // hdidmap and cdidmap init.
- for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
- write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
- write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
- }
-
- write_byte(ebda_seg,&EbdaData->ata.hdcount,0);
- write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
-}
-
-#define TIMEOUT 0
-#define BSY 1
-#define NOT_BSY 2
-#define NOT_BSY_DRQ 3
-#define NOT_BSY_NOT_DRQ 4
-#define NOT_BSY_RDY 5
-
-#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
-
-int await_ide();
-static int await_ide(when_done,base,timeout)
- Bit8u when_done;
- Bit16u base;
- Bit16u timeout;
-{
- Bit32u time=0,last=0;
- Bit16u status;
- Bit8u result;
- status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw one away
- for(;;) {
- status = inb(base+ATA_CB_STAT);
- time++;
- if (when_done == BSY)
- result = status & ATA_CB_STAT_BSY;
- else if (when_done == NOT_BSY)
- result = !(status & ATA_CB_STAT_BSY);
- else if (when_done == NOT_BSY_DRQ)
- result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
- else if (when_done == NOT_BSY_NOT_DRQ)
- result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
- else if (when_done == NOT_BSY_RDY)
- result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
- else if (when_done == TIMEOUT)
- result = 0;
-
- if (result) return 0;
- if (time>>16 != last) // mod 2048 each 16 ms
- {
- last = time >>16;
- BX_DEBUG_ATA("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout);
- }
- if (status & ATA_CB_STAT_ERR)
- {
- BX_DEBUG_ATA("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout);
- return -1;
- }
- if ((timeout == 0) || ((time>>11) > timeout)) break;
- }
- BX_INFO("IDE time out\n");
- return -1;
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : device detection
-// ---------------------------------------------------------------------------
-
-void ata_detect( )
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u hdcount, cdcount, device, type;
- Bit8u buffer[0x0200];
-
-#if BX_MAX_ATA_INTERFACES > 0
- write_byte(ebda_seg,&EbdaData->ata.channels[0].iface,ATA_IFACE_ISA);
- write_word(ebda_seg,&EbdaData->ata.channels[0].iobase1,0x1f0);
- write_word(ebda_seg,&EbdaData->ata.channels[0].iobase2,0x3f0);
- write_byte(ebda_seg,&EbdaData->ata.channels[0].irq,14);
-#endif
-#if BX_MAX_ATA_INTERFACES > 1
- write_byte(ebda_seg,&EbdaData->ata.channels[1].iface,ATA_IFACE_ISA);
- write_word(ebda_seg,&EbdaData->ata.channels[1].iobase1,0x170);
- write_word(ebda_seg,&EbdaData->ata.channels[1].iobase2,0x370);
- write_byte(ebda_seg,&EbdaData->ata.channels[1].irq,15);
-#endif
-#if BX_MAX_ATA_INTERFACES > 2
- write_byte(ebda_seg,&EbdaData->ata.channels[2].iface,ATA_IFACE_ISA);
- write_word(ebda_seg,&EbdaData->ata.channels[2].iobase1,0x1e8);
- write_word(ebda_seg,&EbdaData->ata.channels[2].iobase2,0x3e0);
- write_byte(ebda_seg,&EbdaData->ata.channels[2].irq,12);
-#endif
-#if BX_MAX_ATA_INTERFACES > 3
- write_byte(ebda_seg,&EbdaData->ata.channels[3].iface,ATA_IFACE_ISA);
- write_word(ebda_seg,&EbdaData->ata.channels[3].iobase1,0x168);
- write_word(ebda_seg,&EbdaData->ata.channels[3].iobase2,0x360);
- write_byte(ebda_seg,&EbdaData->ata.channels[3].irq,11);
-#endif
-#if BX_MAX_ATA_INTERFACES > 4
-#error Please fill the ATA interface informations
-#endif
-
- // Device detection
- hdcount=cdcount=0;
-
- for(device=0; device<BX_MAX_ATA_DEVICES; device++) {
- Bit16u iobase1, iobase2;
- Bit8u channel, slave, shift;
- Bit8u sc, sn, cl, ch, st;
-
- channel = device / 2;
- slave = device % 2;
-
- iobase1 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1);
- iobase2 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2);
-
- // Disable interrupts
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-
- // Look for device
- outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
- outb(iobase1+ATA_CB_SC, 0x55);
- outb(iobase1+ATA_CB_SN, 0xaa);
- outb(iobase1+ATA_CB_SC, 0xaa);
- outb(iobase1+ATA_CB_SN, 0x55);
- outb(iobase1+ATA_CB_SC, 0x55);
- outb(iobase1+ATA_CB_SN, 0xaa);
-
- // If we found something
- sc = inb(iobase1+ATA_CB_SC);
- sn = inb(iobase1+ATA_CB_SN);
-
- if ( (sc == 0x55) && (sn == 0xaa) ) {
- write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN);
-
- // reset the channel
- ata_reset(device);
-
- // check for ATA or ATAPI
- outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
- sc = inb(iobase1+ATA_CB_SC);
- sn = inb(iobase1+ATA_CB_SN);
- if ((sc==0x01) && (sn==0x01)) {
- cl = inb(iobase1+ATA_CB_CL);
- ch = inb(iobase1+ATA_CB_CH);
- st = inb(iobase1+ATA_CB_STAT);
-
- if ((cl==0x14) && (ch==0xeb)) {
- write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI);
- } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
- write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA);
- } else if ((cl==0xff) && (ch==0xff)) {
- write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
- }
- }
- }
-
- type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
-
- // Now we send a IDENTIFY command to ATA device
- if(type == ATA_TYPE_ATA) {
- Bit32u sectors_low, sectors_high;
- Bit16u cylinders, heads, spt, blksize;
- Bit8u translation, removable, mode;
-
- //Temporary values to do the transfer
- write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
-
- if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 )
- BX_PANIC("ata-detect: Failed to detect ATA device\n");
-
- removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
- mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
- blksize = read_word(get_SS(),buffer+10);
-
- cylinders = read_word(get_SS(),buffer+(1*2)); // word 1
- heads = read_word(get_SS(),buffer+(3*2)); // word 3
- spt = read_word(get_SS(),buffer+(6*2)); // word 6
-
- if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support
- sectors_low = read_dword(get_SS(),buffer+(100*2)); // word 100 and word 101
- sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and word 103
- } else {
- sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
- sectors_high = 0;
- }
-
- write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
- write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
- write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);
- write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders);
- write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
- write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low);
- write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high);
- BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
-
- translation = inb_cmos(0x39 + channel/2);
- for (shift=device%4; shift>0; shift--) translation >>= 2;
- translation &= 0x03;
-
- write_byte(ebda_seg,&EbdaData->ata.devices[device].translation, translation);
-
- switch (translation) {
- case ATA_TRANSLATION_NONE:
- BX_INFO("none");
- break;
- case ATA_TRANSLATION_LBA:
- BX_INFO("lba");
- break;
- case ATA_TRANSLATION_LARGE:
- BX_INFO("large");
- break;
- case ATA_TRANSLATION_RECHS:
- BX_INFO("r-echs");
- break;
- }
- switch (translation) {
- case ATA_TRANSLATION_NONE:
- break;
- case ATA_TRANSLATION_LBA:
- spt = 63;
- sectors_low /= 63;
- heads = sectors_low / 1024;
- if (heads>128) heads = 255;
- else if (heads>64) heads = 128;
- else if (heads>32) heads = 64;
- else if (heads>16) heads = 32;
- else heads=16;
- cylinders = sectors_low / heads;
- break;
- case ATA_TRANSLATION_RECHS:
- // Take care not to overflow
- if (heads==16) {
- if(cylinders>61439) cylinders=61439;
- heads=15;
- cylinders = (Bit16u)((Bit32u)(cylinders)*16/15);
- }
- // then go through the large bitshift process
- case ATA_TRANSLATION_LARGE:
- while(cylinders > 1024) {
- cylinders >>= 1;
- heads <<= 1;
-
- // If we max out the head count
- if (heads > 127) break;
- }
- break;
- }
- // clip to 1024 cylinders in lchs
- if (cylinders > 1024) cylinders=1024;
- BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
-
- write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);
- write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders);
- write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt);
-
- // fill hdidmap
- write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device);
- hdcount++;
- }
-
- // Now we send a IDENTIFY command to ATAPI device
- if(type == ATA_TYPE_ATAPI) {
-
- Bit8u type, removable, mode;
- Bit16u blksize;
-
- //Temporary values to do the transfer
- write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
-
- if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0)
- BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
-
- type = read_byte(get_SS(),buffer+1) & 0x1f;
- removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
- mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
- blksize = 2048;
-
- write_byte(ebda_seg,&EbdaData->ata.devices[device].device, type);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
- write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
- write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
-
- // fill cdidmap
- write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device);
- cdcount++;
- }
-
- {
- Bit32u sizeinmb;
- Bit16u ataversion;
- Bit8u c, i, version, model[41];
-
- switch (type) {
- case ATA_TYPE_ATA:
- sizeinmb = (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21)
- | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) >> 11);
- case ATA_TYPE_ATAPI:
- // Read ATA/ATAPI version
- ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
- for(version=15;version>0;version--) {
- if((ataversion&(1<<version))!=0)
- break;
- }
-
- // Read model name
- for(i=0;i<20;i++){
- write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
- write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
- }
-
- // Reformat
- write_byte(get_SS(),model+40,0x00);
- for(i=39;i>0;i--){
- if(read_byte(get_SS(),model+i)==0x20)
- write_byte(get_SS(),model+i,0x00);
- else break;
- }
- if (i>36) {
- write_byte(get_SS(),model+36,0x00);
- for(i=35;i>32;i--){
- write_byte(get_SS(),model+i,0x2E);
- }
- }
- break;
- }
-
- switch (type) {
- case ATA_TYPE_ATA:
- printf("ata%d %s: ",channel,slave?" slave":"master");
- i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
- if (sizeinmb < (1UL<<16))
- printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb);
- else
- printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10));
- break;
- case ATA_TYPE_ATAPI:
- printf("ata%d %s: ",channel,slave?" slave":"master");
- i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
- if(read_byte(ebda_seg,&EbdaData->ata.devices[device].device)==ATA_DEVICE_CDROM)
- printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version);
- else
- printf(" ATAPI-%d Device\n",version);
- break;
- case ATA_TYPE_UNKNOWN:
- printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
- break;
- }
- }
- }
-
- // Store the devices counts
- write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
- write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount);
- write_byte(0x40,0x75, hdcount);
-
- printf("\n");
-
- // FIXME : should use bios=cmos|auto|disable bits
- // FIXME : should know about translation bits
- // FIXME : move hard_drive_post here
-
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : software reset
-// ---------------------------------------------------------------------------
-// ATA-3
-// 8.2.1 Software reset - Device 0
-
-void ata_reset(device)
-Bit16u device;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u iobase1, iobase2;
- Bit8u channel, slave, sn, sc;
- Bit8u type;
- Bit16u max;
-
- channel = device / 2;
- slave = device % 2;
-
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
-
- // Reset
-
-// 8.2.1 (a) -- set SRST in DC
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
-
-// 8.2.1 (b) -- wait for BSY
- await_ide(BSY, iobase1, 20);
-
-// 8.2.1 (f) -- clear SRST
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-
- type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
- if (type != ATA_TYPE_NONE) {
-
-// 8.2.1 (g) -- check for sc==sn==0x01
- // select device
- outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
- sc = inb(iobase1+ATA_CB_SC);
- sn = inb(iobase1+ATA_CB_SN);
-
- if ( (sc==0x01) && (sn==0x01) ) {
- if (type == ATA_TYPE_ATA) //ATA
- await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
- else //ATAPI
- await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
- }
-
-// 8.2.1 (h) -- wait for not BSY
- await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
- }
-
- // Enable interrupts
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a non data command
-// ---------------------------------------------------------------------------
-
-Bit16u ata_cmd_non_data()
-{return 0;}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a data-in command
-// ---------------------------------------------------------------------------
- // returns
- // 0 : no error
- // 1 : BUSY bit set
- // 2 : read error
- // 3 : expected DRQ=1
- // 4 : no sectors left to read/verify
- // 5 : more sectors to read/verify
- // 6 : no sectors left to write
- // 7 : more sectors to write
-Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
-Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba_low, lba_high;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u iobase1, iobase2, blksize;
- Bit8u channel, slave;
- Bit8u status, current, mode;
-
- channel = device / 2;
- slave = device % 2;
-
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
- mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
- blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
- if (mode == ATA_MODE_PIO32) blksize>>=2;
- else blksize>>=1;
-
- // Reset count of transferred data
- write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
- write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
- current = 0;
-
- status = inb(iobase1 + ATA_CB_STAT);
- if (status & ATA_CB_STAT_BSY) return 1;
-
- outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-
- // sector will be 0 only on lba access. Convert to lba-chs
- if (sector == 0) {
- if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
- outb(iobase1 + ATA_CB_FR, 0x00);
- outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
- outb(iobase1 + ATA_CB_SN, lba_low >> 24);
- outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
- outb(iobase1 + ATA_CB_CH, lba_high >> 8);
- command |= 0x04;
- count &= (1UL << 8) - 1;
- lba_low &= (1UL << 24) - 1;
- }
- sector = (Bit16u) (lba_low & 0x000000ffL);
- cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
- head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
- }
-
- outb(iobase1 + ATA_CB_FR, 0x00);
- outb(iobase1 + ATA_CB_SC, count);
- outb(iobase1 + ATA_CB_SN, sector);
- outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
- outb(iobase1 + ATA_CB_CH, cylinder >> 8);
- outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
- outb(iobase1 + ATA_CB_CMD, command);
-
- await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
- status = inb(iobase1 + ATA_CB_STAT);
-
- if (status & ATA_CB_STAT_ERR) {
- BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
- return 2;
- } else if ( !(status & ATA_CB_STAT_DRQ) ) {
- BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n", (unsigned) status);
- return 3;
- }
-
- // FIXME : move seg/off translation here
-
-ASM_START
- sti ;; enable higher priority interrupts
-ASM_END
-
- while (1) {
-
-ASM_START
- push bp
- mov bp, sp
- mov di, _ata_cmd_data_in.offset + 2[bp]
- mov ax, _ata_cmd_data_in.segment + 2[bp]
- mov cx, _ata_cmd_data_in.blksize + 2[bp]
-
- ;; adjust if there will be an overrun. 2K max sector size
- cmp di, #0xf800 ;;
- jbe ata_in_no_adjust
-
-ata_in_adjust:
- sub di, #0x0800 ;; sub 2 kbytes from offset
- add ax, #0x0080 ;; add 2 Kbytes to segment
-
-ata_in_no_adjust:
- mov es, ax ;; segment in es
-
- mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port
-
- mov ah, _ata_cmd_data_in.mode + 2[bp]
- cmp ah, #ATA_MODE_PIO32
- je ata_in_32
-
-ata_in_16:
- rep
- insw ;; CX words transfered from port(DX) to ES:[DI]
- jmp ata_in_done
-
-ata_in_32:
- rep
- insd ;; CX dwords transfered from port(DX) to ES:[DI]
-
-ata_in_done:
- mov _ata_cmd_data_in.offset + 2[bp], di
- mov _ata_cmd_data_in.segment + 2[bp], es
- pop bp
-ASM_END
-
- current++;
- write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
- count--;
- await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
- status = inb(iobase1 + ATA_CB_STAT);
- if (count == 0) {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
- != ATA_CB_STAT_RDY ) {
- BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status);
- return 4;
- }
- break;
- }
- else {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
- != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
- BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status);
- return 5;
- }
- continue;
- }
- }
- // Enable interrupts
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
- return 0;
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a data-out command
-// ---------------------------------------------------------------------------
- // returns
- // 0 : no error
- // 1 : BUSY bit set
- // 2 : read error
- // 3 : expected DRQ=1
- // 4 : no sectors left to read/verify
- // 5 : more sectors to read/verify
- // 6 : no sectors left to write
- // 7 : more sectors to write
-Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
-Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba_low, lba_high;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u iobase1, iobase2, blksize;
- Bit8u channel, slave;
- Bit8u status, current, mode;
-
- channel = device / 2;
- slave = device % 2;
-
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
- mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
- blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
- if (mode == ATA_MODE_PIO32) blksize>>=2;
- else blksize>>=1;
-
- // Reset count of transferred data
- write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
- write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
- current = 0;
-
- status = inb(iobase1 + ATA_CB_STAT);
- if (status & ATA_CB_STAT_BSY) return 1;
-
- outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-
- // sector will be 0 only on lba access. Convert to lba-chs
- if (sector == 0) {
- if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
- outb(iobase1 + ATA_CB_FR, 0x00);
- outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
- outb(iobase1 + ATA_CB_SN, lba_low >> 24);
- outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
- outb(iobase1 + ATA_CB_CH, lba_high >> 8);
- command |= 0x04;
- count &= (1UL << 8) - 1;
- lba_low &= (1UL << 24) - 1;
- }
- sector = (Bit16u) (lba_low & 0x000000ffL);
- cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
- head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
- }
-
- outb(iobase1 + ATA_CB_FR, 0x00);
- outb(iobase1 + ATA_CB_SC, count);
- outb(iobase1 + ATA_CB_SN, sector);
- outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
- outb(iobase1 + ATA_CB_CH, cylinder >> 8);
- outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
- outb(iobase1 + ATA_CB_CMD, command);
-
- await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
- status = inb(iobase1 + ATA_CB_STAT);
-
- if (status & ATA_CB_STAT_ERR) {
- BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
- return 2;
- } else if ( !(status & ATA_CB_STAT_DRQ) ) {
- BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n", (unsigned) status);
- return 3;
- }
-
- // FIXME : move seg/off translation here
-
-ASM_START
- sti ;; enable higher priority interrupts
-ASM_END
-
- while (1) {
-
-ASM_START
- push bp
- mov bp, sp
- mov si, _ata_cmd_data_out.offset + 2[bp]
- mov ax, _ata_cmd_data_out.segment + 2[bp]
- mov cx, _ata_cmd_data_out.blksize + 2[bp]
-
- ;; adjust if there will be an overrun. 2K max sector size
- cmp si, #0xf800 ;;
- jbe ata_out_no_adjust
-
-ata_out_adjust:
- sub si, #0x0800 ;; sub 2 kbytes from offset
- add ax, #0x0080 ;; add 2 Kbytes to segment
-
-ata_out_no_adjust:
- mov es, ax ;; segment in es
-
- mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port
-
- mov ah, _ata_cmd_data_out.mode + 2[bp]
- cmp ah, #ATA_MODE_PIO32
- je ata_out_32
-
-ata_out_16:
- seg ES
- rep
- outsw ;; CX words transfered from port(DX) to ES:[SI]
- jmp ata_out_done
-
-ata_out_32:
- seg ES
- rep
- outsd ;; CX dwords transfered from port(DX) to ES:[SI]
-
-ata_out_done:
- mov _ata_cmd_data_out.offset + 2[bp], si
- mov _ata_cmd_data_out.segment + 2[bp], es
- pop bp
-ASM_END
-
- current++;
- write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
- count--;
- status = inb(iobase1 + ATA_CB_STAT);
- if (count == 0) {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
- != ATA_CB_STAT_RDY ) {
- BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status);
- return 6;
- }
- break;
- }
- else {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
- != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
- BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status);
- return 7;
- }
- continue;
- }
- }
- // Enable interrupts
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
- return 0;
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a packet command
-// ---------------------------------------------------------------------------
- // returns
- // 0 : no error
- // 1 : error in parameters
- // 2 : BUSY bit set
- // 3 : error
- // 4 : not ready
-Bit16u ata_cmd_packet(device, cmdlen, cmdseg, cmdoff, header, length, inout, bufseg, bufoff)
-Bit8u cmdlen,inout;
-Bit16u device,cmdseg, cmdoff, bufseg, bufoff;
-Bit16u header;
-Bit32u length;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u iobase1, iobase2;
- Bit16u lcount, lbefore, lafter, count;
- Bit8u channel, slave;
- Bit8u status, mode, lmode;
- Bit32u total, transfer;
-
- channel = device / 2;
- slave = device % 2;
-
- // Data out is not supported yet
- if (inout == ATA_DATA_OUT) {
- BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n");
- return 1;
- }
-
- // The header length must be even
- if (header & 1) {
- BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header);
- return 1;
- }
-
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
- mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
- transfer= 0L;
-
- if (cmdlen < 12) cmdlen=12;
- if (cmdlen > 12) cmdlen=16;
- cmdlen>>=1;
-
- // Reset count of transferred data
- write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
- write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
-
- status = inb(iobase1 + ATA_CB_STAT);
- if (status & ATA_CB_STAT_BSY) return 2;
-
- outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
- outb(iobase1 + ATA_CB_FR, 0x00);
- outb(iobase1 + ATA_CB_SC, 0x00);
- outb(iobase1 + ATA_CB_SN, 0x00);
- outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
- outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
- outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
- outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
-
- // Device should ok to receive command
- await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
- status = inb(iobase1 + ATA_CB_STAT);
-
- if (status & ATA_CB_STAT_ERR) {
- BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
- return 3;
- } else if ( !(status & ATA_CB_STAT_DRQ) ) {
- BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status);
- return 4;
- }
-
- // Normalize address
- cmdseg += (cmdoff / 16);
- cmdoff %= 16;
-
- // Send command to device
-ASM_START
- sti ;; enable higher priority interrupts
-
- push bp
- mov bp, sp
-
- mov si, _ata_cmd_packet.cmdoff + 2[bp]
- mov ax, _ata_cmd_packet.cmdseg + 2[bp]
- mov cx, _ata_cmd_packet.cmdlen + 2[bp]
- mov es, ax ;; segment in es
-
- mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port
-
- seg ES
- rep
- outsw ;; CX words transfered from port(DX) to ES:[SI]
-
- pop bp
-ASM_END
-
- if (inout == ATA_DATA_NO) {
- await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
- status = inb(iobase1 + ATA_CB_STAT);
- }
- else {
- Bit16u loops = 0;
- Bit8u sc;
- while (1) {
-
- if (loops == 0) {//first time through
- status = inb(iobase2 + ATA_CB_ASTAT);
- await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
- }
- else
- await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
- loops++;
-
- status = inb(iobase1 + ATA_CB_STAT);
- sc = inb(iobase1 + ATA_CB_SC);
-
- // Check if command completed
- if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
- ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) break;
-
- if (status & ATA_CB_STAT_ERR) {
- BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
- return 3;
- }
-
- // Normalize address
- bufseg += (bufoff / 16);
- bufoff %= 16;
-
- // Get the byte count
- lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
-
- // adjust to read what we want
- if(header>lcount) {
- lbefore=lcount;
- header-=lcount;
- lcount=0;
- }
- else {
- lbefore=header;
- header=0;
- lcount-=lbefore;
- }
-
- if(lcount>length) {
- lafter=lcount-length;
- lcount=length;
- length=0;
- }
- else {
- lafter=0;
- length-=lcount;
- }
-
- // Save byte count
- count = lcount;
-
- BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
- BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff);
-
- // If counts not dividable by 4, use 16bits mode
- lmode = mode;
- if (lbefore & 0x03) lmode=ATA_MODE_PIO16;
- if (lcount & 0x03) lmode=ATA_MODE_PIO16;
- if (lafter & 0x03) lmode=ATA_MODE_PIO16;
-
- // adds an extra byte if count are odd. before is always even
- if (lcount & 0x01) {
- lcount+=1;
- if ((lafter > 0) && (lafter & 0x01)) {
- lafter-=1;
- }
- }
-
- if (lmode == ATA_MODE_PIO32) {
- lcount>>=2; lbefore>>=2; lafter>>=2;
- }
- else {
- lcount>>=1; lbefore>>=1; lafter>>=1;
- }
-
- ; // FIXME bcc bug
-
-ASM_START
- push bp
- mov bp, sp
-
- mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port
-
- mov cx, _ata_cmd_packet.lbefore + 2[bp]
- jcxz ata_packet_no_before
-
- mov ah, _ata_cmd_packet.lmode + 2[bp]
- cmp ah, #ATA_MODE_PIO32
- je ata_packet_in_before_32
-
-ata_packet_in_before_16:
- in ax, dx
- loop ata_packet_in_before_16
- jmp ata_packet_no_before
-
-ata_packet_in_before_32:
- push eax
-ata_packet_in_before_32_loop:
- in eax, dx
- loop ata_packet_in_before_32_loop
- pop eax
-
-ata_packet_no_before:
- mov cx, _ata_cmd_packet.lcount + 2[bp]
- jcxz ata_packet_after
-
- mov di, _ata_cmd_packet.bufoff + 2[bp]
- mov ax, _ata_cmd_packet.bufseg + 2[bp]
- mov es, ax
-
- mov ah, _ata_cmd_packet.lmode + 2[bp]
- cmp ah, #ATA_MODE_PIO32
- je ata_packet_in_32
-
-ata_packet_in_16:
- rep
- insw ;; CX words transfered tp port(DX) to ES:[DI]
- jmp ata_packet_after
-
-ata_packet_in_32:
- rep
- insd ;; CX dwords transfered to port(DX) to ES:[DI]
-
-ata_packet_after:
- mov cx, _ata_cmd_packet.lafter + 2[bp]
- jcxz ata_packet_done
-
- mov ah, _ata_cmd_packet.lmode + 2[bp]
- cmp ah, #ATA_MODE_PIO32
- je ata_packet_in_after_32
-
-ata_packet_in_after_16:
- in ax, dx
- loop ata_packet_in_after_16
- jmp ata_packet_done
-
-ata_packet_in_after_32:
- push eax
-ata_packet_in_after_32_loop:
- in eax, dx
- loop ata_packet_in_after_32_loop
- pop eax
-
-ata_packet_done:
- pop bp
-ASM_END
-
- // Compute new buffer address
- bufoff += count;
-
- // Save transferred bytes count
- transfer += count;
- write_dword(ebda_seg, &EbdaData->ata.trsfbytes,transfer);
- }
- }
-
- // Final check, device must be ready
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
- != ATA_CB_STAT_RDY ) {
- BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status);
- return 4;
- }
-
- // Enable interrupts
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
- return 0;
-}
-
-// ---------------------------------------------------------------------------
-// End of ATA/ATAPI Driver
-// ---------------------------------------------------------------------------
-
-// ---------------------------------------------------------------------------
-// Start of ATA/ATAPI generic functions
-// ---------------------------------------------------------------------------
-
- Bit16u
-atapi_get_sense(device, seg, asc, ascq)
- Bit16u device;
-{
- Bit8u atacmd[12];
- Bit8u buffer[18];
- Bit8u i;
-
- memsetb(get_SS(),atacmd,0,12);
-
- // Request SENSE
- atacmd[0]=ATA_CMD_REQUEST_SENSE;
- atacmd[4]=sizeof(buffer);
- if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, get_SS(), buffer) != 0)
- return 0x0002;
-
- write_byte(seg,asc,buffer[12]);
- write_byte(seg,ascq,buffer[13]);
-
- return 0;
-}
-
- Bit16u
-atapi_is_ready(device)
- Bit16u device;
-{
- Bit8u packet[12];
- Bit8u buf[8];
- Bit32u block_len;
- Bit32u sectors;
- Bit32u timeout; //measured in ms
- Bit32u time;
- Bit8u asc, ascq;
- Bit8u in_progress;
- Bit16u ebda_seg = read_word(0x0040,0x000E);
- if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI) {
- printf("not implemented for non-ATAPI device\n");
- return -1;
- }
-
- BX_DEBUG_ATA("ata_detect_medium: begin\n");
- memsetb(get_SS(),packet, 0, sizeof packet);
- packet[0] = 0x25; /* READ CAPACITY */
-
- /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT
- * is reported by the device. If the device reports "IN PROGRESS",
- * 30 seconds is added. */
- timeout = 5000;
- time = 0;
- in_progress = 0;
- while (time < timeout) {
- if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L, ATA_DATA_IN, get_SS(), buf) == 0)
- goto ok;
-
- if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) {
- if (asc == 0x3a) { /* MEDIUM NOT PRESENT */
- BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n");
- return -1;
- }
-
- if (asc == 0x04 && ascq == 0x01 && !in_progress) {
- /* IN PROGRESS OF BECOMING READY */
- printf("Waiting for device to detect medium... ");
- /* Allow 30 seconds more */
- timeout = 30000;
- in_progress = 1;
- }
- }
- time += 100;
- }
- BX_DEBUG_ATA("read capacity failed\n");
- return -1;
-ok:
-
- block_len = (Bit32u) buf[4] << 24
- | (Bit32u) buf[5] << 16
- | (Bit32u) buf[6] << 8
- | (Bit32u) buf[7] << 0;
- BX_DEBUG_ATA("block_len=%u\n", block_len);
-
- if (block_len!= 2048 && block_len!= 512)
- {
- printf("Unsupported sector size %u\n", block_len);
- return -1;
- }
- write_dword(ebda_seg,&EbdaData->ata.devices[device].blksize, block_len);
-
- sectors = (Bit32u) buf[0] << 24
- | (Bit32u) buf[1] << 16
- | (Bit32u) buf[2] << 8
- | (Bit32u) buf[3] << 0;
-
- BX_DEBUG_ATA("sectors=%u\n", sectors);
- if (block_len == 2048)
- sectors <<= 2; /* # of sectors in 512-byte "soft" sector */
- if (sectors != read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low))
- printf("%dMB medium detected\n", sectors>>(20-9));
- write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);
- return 0;
-}
-
- Bit16u
-atapi_is_cdrom(device)
- Bit8u device;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
-
- if (device >= BX_MAX_ATA_DEVICES)
- return 0;
-
- if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI)
- return 0;
-
- if (read_byte(ebda_seg,&EbdaData->ata.devices[device].device) != ATA_DEVICE_CDROM)
- return 0;
-
- return 1;
-}
-
-// ---------------------------------------------------------------------------
-// End of ATA/ATAPI generic functions
-// ---------------------------------------------------------------------------
-
-#endif // BX_USE_ATADRV
-
-#if BX_ELTORITO_BOOT
-
-// ---------------------------------------------------------------------------
-// Start of El-Torito boot functions
-// ---------------------------------------------------------------------------
-
- void
-cdemu_init()
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
-
- // the only important data is this one for now
- write_byte(ebda_seg,&EbdaData->cdemu.active,0x00);
-}
-
- Bit8u
-cdemu_isactive()
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
-
- return(read_byte(ebda_seg,&EbdaData->cdemu.active));
-}
-
- Bit8u
-cdemu_emulated_drive()
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
-
- return(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive));
-}
-
-static char isotag[6]="CD001";
-static char eltorito[24]="EL TORITO SPECIFICATION";
-//
-// Returns ah: emulated drive, al: error code
-//
- Bit16u
-cdrom_boot()
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u atacmd[12], buffer[2048];
- Bit32u lba;
- Bit16u boot_segment, nbsectors, i, error;
- Bit8u device;
-
- // Find out the first cdrom
- for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
- if (atapi_is_cdrom(device)) break;
- }
-
- // if not found
- if(device >= BX_MAX_ATA_DEVICES) return 2;
-
- if(error = atapi_is_ready(device) != 0)
- BX_INFO("ata_is_ready returned %d\n",error);
-
- // Read the Boot Record Volume Descriptor
- memsetb(get_SS(),atacmd,0,12);
- atacmd[0]=0x28; // READ command
- atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors
- atacmd[8]=(0x01 & 0x00ff); // Sectors
- atacmd[2]=(0x11 & 0xff000000) >> 24; // LBA
- atacmd[3]=(0x11 & 0x00ff0000) >> 16;
- atacmd[4]=(0x11 & 0x0000ff00) >> 8;
- atacmd[5]=(0x11 & 0x000000ff);
- if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
- return 3;
-
- // Validity checks
- if(buffer[0]!=0)return 4;
- for(i=0;i<5;i++){
- if(buffer[1+i]!=read_byte(0xf000,&isotag[i]))return 5;
- }
- for(i=0;i<23;i++)
- if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6;
-
- // ok, now we calculate the Boot catalog address
- lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47];
-
- // And we read the Boot Catalog
- memsetb(get_SS(),atacmd,0,12);
- atacmd[0]=0x28; // READ command
- atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors
- atacmd[8]=(0x01 & 0x00ff); // Sectors
- atacmd[2]=(lba & 0xff000000) >> 24; // LBA
- atacmd[3]=(lba & 0x00ff0000) >> 16;
- atacmd[4]=(lba & 0x0000ff00) >> 8;
- atacmd[5]=(lba & 0x000000ff);
- if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
- return 7;
-
- // Validation entry
- if(buffer[0x00]!=0x01)return 8; // Header
- if(buffer[0x01]!=0x00)return 9; // Platform
- if(buffer[0x1E]!=0x55)return 10; // key 1
- if(buffer[0x1F]!=0xAA)return 10; // key 2
-
- // Initial/Default Entry
- if(buffer[0x20]!=0x88)return 11; // Bootable
-
- write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]);
- if(buffer[0x21]==0){
- // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
- // Win2000 cd boot needs to know it booted from cd
- write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0);
- }
- else if(buffer[0x21]<4)
- write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00);
- else
- write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x80);
-
- write_byte(ebda_seg,&EbdaData->cdemu.controller_index,device/2);
- write_byte(ebda_seg,&EbdaData->cdemu.device_spec,device%2);
-
- boot_segment=buffer[0x23]*0x100+buffer[0x22];
- if(boot_segment==0x0000)boot_segment=0x07C0;
-
- write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment);
- write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000);
-
- nbsectors=buffer[0x27]*0x100+buffer[0x26];
- write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors);
-
- lba=buffer[0x2B]*0x1000000+buffer[0x2A]*0x10000+buffer[0x29]*0x100+buffer[0x28];
- write_dword(ebda_seg,&EbdaData->cdemu.ilba,lba);
-
- // And we read the image in memory
- memsetb(get_SS(),atacmd,0,12);
- atacmd[0]=0x28; // READ command
- atacmd[7]=((1+(nbsectors-1)/4) & 0xff00) >> 8; // Sectors
- atacmd[8]=((1+(nbsectors-1)/4) & 0x00ff); // Sectors
- atacmd[2]=(lba & 0xff000000) >> 24; // LBA
- atacmd[3]=(lba & 0x00ff0000) >> 16;
- atacmd[4]=(lba & 0x0000ff00) >> 8;
- atacmd[5]=(lba & 0x000000ff);
- if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0)
- return 12;
-
- // Remember the media type
- switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
- case 0x01: // 1.2M floppy
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,15);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
- break;
- case 0x02: // 1.44M floppy
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,18);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
- break;
- case 0x03: // 2.88M floppy
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,36);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
- break;
- case 0x04: // Harddrive
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,
- (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1);
- write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1);
- break;
- }
-
- if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) {
- // Increase bios installed hardware number of devices
- if(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)==0x00)
- write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41);
- else
- write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1);
- }
-
-
- // everything is ok, so from now on, the emulation is active
- if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0)
- write_byte(ebda_seg,&EbdaData->cdemu.active,0x01);
-
- // return the boot drive + no error
- return (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)*0x100)+0;
-}
-
-// ---------------------------------------------------------------------------
-// End of El-Torito boot functions
-// ---------------------------------------------------------------------------
-#endif // BX_ELTORITO_BOOT
-
- void
-int14_function(regs, ds, iret_addr)
- pusha_regs_t regs; // regs pushed from PUSHA instruction
- Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper
- iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call
-{
- Bit16u addr,timer,val16;
- Bit8u timeout;
-
- ASM_START
- sti
- ASM_END
-
- addr = read_word(0x0040, (regs.u.r16.dx << 1));
- timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx);
- if ((regs.u.r16.dx < 4) && (addr > 0)) {
- switch (regs.u.r8.ah) {
- case 0:
- outb(addr+3, inb(addr+3) | 0x80);
- if (regs.u.r8.al & 0xE0 == 0) {
- outb(addr, 0x17);
- outb(addr+1, 0x04);
- } else {
- val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5);
- outb(addr, val16 & 0xFF);
- outb(addr+1, val16 >> 8);
- }
- outb(addr+3, regs.u.r8.al & 0x1F);
- regs.u.r8.ah = inb(addr+5);
- regs.u.r8.al = inb(addr+6);
- ClearCF(iret_addr.flags);
- break;
- case 1:
- timer = read_word(0x0040, 0x006C);
- while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) {
- val16 = read_word(0x0040, 0x006C);
- if (val16 != timer) {
- timer = val16;
- timeout--;
- }
- }
- if (timeout) outb(addr, regs.u.r8.al);
- regs.u.r8.ah = inb(addr+5);
- if (!timeout) regs.u.r8.ah |= 0x80;
- ClearCF(iret_addr.flags);
- break;
- case 2:
- timer = read_word(0x0040, 0x006C);
- while (((inb(addr+5) & 0x01) == 0) && (timeout)) {
- val16 = read_word(0x0040, 0x006C);
- if (val16 != timer) {
- timer = val16;
- timeout--;
- }
- }
- if (timeout) {
- regs.u.r8.ah = 0;
- regs.u.r8.al = inb(addr);
- } else {
- regs.u.r8.ah = inb(addr+5);
- }
- ClearCF(iret_addr.flags);
- break;
- case 3:
- regs.u.r8.ah = inb(addr+5);
- regs.u.r8.al = inb(addr+6);
- ClearCF(iret_addr.flags);
- break;
- default:
- SetCF(iret_addr.flags); // Unsupported
- }
- } else {
- SetCF(iret_addr.flags); // Unsupported
- }
-}
-
- void
-int15_function(regs, ES, DS, FLAGS)
- pusha_regs_t regs; // REGS pushed via pusha
- Bit16u ES, DS, FLAGS;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- bx_bool prev_a20_enable;
- Bit16u base15_00;
- Bit8u base23_16;
- Bit16u ss;
- Bit16u CX,DX;
-
- Bit16u bRegister;
- Bit8u irqDisable;
-
-BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
-
- switch (regs.u.r8.ah) {
- case 0x24: /* A20 Control */
- switch (regs.u.r8.al) {
- case 0x00:
- set_enable_a20(0);
- CLEAR_CF();
- regs.u.r8.ah = 0;
- break;
- case 0x01:
- set_enable_a20(1);
- CLEAR_CF();
- regs.u.r8.ah = 0;
- break;
- case 0x02:
- regs.u.r8.al = (inb(0x92) >> 1) & 0x01;
- CLEAR_CF();
- regs.u.r8.ah = 0;
- break;
- case 0x03:
- CLEAR_CF();
- regs.u.r8.ah = 0;
- regs.u.r16.bx = 3;
- break;
- default:
- BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) regs.u.r8.al);
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- break;
-
- case 0x41:
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
-
- case 0x4f:
- /* keyboard intercept */
-#if BX_CPU < 2
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
-#else
- // nop
-#endif
- SET_CF();
- break;
-
- case 0x52: // removable media eject
- CLEAR_CF();
- regs.u.r8.ah = 0; // "ok ejection may proceed"
- break;
-
- case 0x83: {
- if( regs.u.r8.al == 0 ) {
- // Set Interval requested.
- if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) {
- // Interval not already set.
- write_byte( 0x40, 0xA0, 1 ); // Set status byte.
- write_word( 0x40, 0x98, ES ); // Byte location, segment
- write_word( 0x40, 0x9A, regs.u.r16.bx ); // Byte location, offset
- write_word( 0x40, 0x9C, regs.u.r16.dx ); // Low word, delay
- write_word( 0x40, 0x9E, regs.u.r16.cx ); // High word, delay.
- CLEAR_CF( );
- irqDisable = inb( 0xA1 );
- outb( 0xA1, irqDisable & 0xFE );
- bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through.
- outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer
- } else {
- // Interval already set.
- BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" );
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- } else if( regs.u.r8.al == 1 ) {
- // Clear Interval requested
- write_byte( 0x40, 0xA0, 0 ); // Clear status byte
- CLEAR_CF( );
- bRegister = inb_cmos( 0xB );
- outb_cmos( 0xB, bRegister & ~0x40 ); // Turn off the Periodic Interrupt timer
- } else {
- BX_DEBUG_INT15("int15: Func 83h, failed.\n" );
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- regs.u.r8.al--;
- }
-
- break;
- }
-
- case 0x87:
-#if BX_CPU < 3
-# error "Int15 function 87h not supported on < 80386"
-#endif
- // +++ should probably have descriptor checks
- // +++ should have exception handlers
-
- // turn off interrupts
-ASM_START
- cli
-ASM_END
-
- prev_a20_enable = set_enable_a20(1); // enable A20 line
-
- // 128K max of transfer on 386+ ???
- // source == destination ???
-
- // ES:SI points to descriptor table
- // offset use initially comments
- // ==============================================
- // 00..07 Unused zeros Null descriptor
- // 08..0f GDT zeros filled in by BIOS
- // 10..17 source ssssssss source of data
- // 18..1f dest dddddddd destination of data
- // 20..27 CS zeros filled in by BIOS
- // 28..2f SS zeros filled in by BIOS
-
- //es:si
- //eeee0
- //0ssss
- //-----
-
-// check for access rights of source & dest here
-
- // Initialize GDT descriptor
- base15_00 = (ES << 4) + regs.u.r16.si;
- base23_16 = ES >> 12;
- if (base15_00 < (ES<<4))
- base23_16++;
- write_word(ES, regs.u.r16.si+0x08+0, 47); // limit 15:00 = 6 * 8bytes/descriptor
- write_word(ES, regs.u.r16.si+0x08+2, base15_00);// base 15:00
- write_byte(ES, regs.u.r16.si+0x08+4, base23_16);// base 23:16
- write_byte(ES, regs.u.r16.si+0x08+5, 0x93); // access
- write_word(ES, regs.u.r16.si+0x08+6, 0x0000); // base 31:24/reserved/limit 19:16
-
- // Initialize CS descriptor
- write_word(ES, regs.u.r16.si+0x20+0, 0xffff);// limit 15:00 = normal 64K limit
- write_word(ES, regs.u.r16.si+0x20+2, 0x0000);// base 15:00
- write_byte(ES, regs.u.r16.si+0x20+4, 0x000f);// base 23:16
- write_byte(ES, regs.u.r16.si+0x20+5, 0x9b); // access
- write_word(ES, regs.u.r16.si+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16
-
- // Initialize SS descriptor
- ss = get_SS();
- base15_00 = ss << 4;
- base23_16 = ss >> 12;
- write_word(ES, regs.u.r16.si+0x28+0, 0xffff); // limit 15:00 = normal 64K limit
- write_word(ES, regs.u.r16.si+0x28+2, base15_00);// base 15:00
- write_byte(ES, regs.u.r16.si+0x28+4, base23_16);// base 23:16
- write_byte(ES, regs.u.r16.si+0x28+5, 0x93); // access
- write_word(ES, regs.u.r16.si+0x28+6, 0x0000); // base 31:24/reserved/limit 19:16
-
- CX = regs.u.r16.cx;
-ASM_START
- // Compile generates locals offset info relative to SP.
- // Get CX (word count) from stack.
- mov bx, sp
- SEG SS
- mov cx, _int15_function.CX [bx]
-
- // since we need to set SS:SP, save them to the BDA
- // for future restore
- push eax
- xor eax, eax
- mov ds, ax
- mov 0x0469, ss
- mov 0x0467, sp
-
- SEG ES
- lgdt [si + 0x08]
- SEG CS
- lidt [pmode_IDT_info]
- ;; perhaps do something with IDT here
-
- ;; set PE bit in CR0
- mov eax, cr0
- or al, #0x01
- mov cr0, eax
- ;; far jump to flush CPU queue after transition to protected mode
- JMP_AP(0x0020, protected_mode)
-
-protected_mode:
- ;; GDT points to valid descriptor table, now load SS, DS, ES
- mov ax, #0x28 ;; 101 000 = 5th descriptor in table, TI=GDT, RPL=00
- mov ss, ax
- mov ax, #0x10 ;; 010 000 = 2nd descriptor in table, TI=GDT, RPL=00
- mov ds, ax
- mov ax, #0x18 ;; 011 000 = 3rd descriptor in table, TI=GDT, RPL=00
- mov es, ax
- xor si, si
- xor di, di
- cld
- rep
- movsw ;; move CX words from DS:SI to ES:DI
-
- ;; make sure DS and ES limits are 64KB
- mov ax, #0x28
- mov ds, ax
- mov es, ax
-
- ;; reset PG bit in CR0 ???
- mov eax, cr0
- and al, #0xFE
- mov cr0, eax
-
- ;; far jump to flush CPU queue after transition to real mode
- JMP_AP(0xf000, real_mode)
-
-real_mode:
- ;; restore IDT to normal real-mode defaults
- SEG CS
- lidt [rmode_IDT_info]
-
- // restore SS:SP from the BDA
- xor ax, ax
- mov ds, ax
- mov ss, 0x0469
- mov sp, 0x0467
- pop eax
-ASM_END
-
- set_enable_a20(prev_a20_enable);
-
- // turn back on interrupts
-ASM_START
- sti
-ASM_END
-
- regs.u.r8.ah = 0;
- CLEAR_CF();
- break;
-
-
- case 0x88:
- // Get the amount of extended memory (above 1M)
-#if BX_CPU < 2
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- SET_CF();
-#else
- regs.u.r8.al = inb_cmos(0x30);
- regs.u.r8.ah = inb_cmos(0x31);
-
- // According to Ralf Brown's interrupt the limit should be 15M,
- // but real machines mostly return max. 63M.
- if(regs.u.r16.ax > 0xffc0)
- regs.u.r16.ax = 0xffc0;
-
- CLEAR_CF();
-#endif
- break;
-
- case 0x90:
- /* Device busy interrupt. Called by Int 16h when no key available */
- break;
-
- case 0x91:
- /* Interrupt complete. Called by Int 16h when key becomes available */
- break;
-
- case 0xbf:
- BX_INFO("*** int 15h function AH=bf not yet supported!\n");
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
-
- case 0xC0:
-#if 0
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
-#endif
- CLEAR_CF();
- regs.u.r8.ah = 0;
- regs.u.r16.bx = BIOS_CONFIG_TABLE;
- ES = 0xF000;
- break;
-
- case 0xc1:
- ES = ebda_seg;
- CLEAR_CF();
- break;
-
- case 0xd8:
- bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n");
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
-
- default:
- BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
- (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
- }
-}
-
-#if BX_USE_PS2_MOUSE
- void
-int15_function_mouse(regs, ES, DS, FLAGS)
- pusha_regs_t regs; // REGS pushed via pusha
- Bit16u ES, DS, FLAGS;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u mouse_flags_1, mouse_flags_2;
- Bit16u mouse_driver_seg;
- Bit16u mouse_driver_offset;
- Bit8u comm_byte, prev_command_byte;
- Bit8u ret, mouse_data1, mouse_data2, mouse_data3;
-
-BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
-
- switch (regs.u.r8.ah) {
- case 0xC2:
- // Return Codes status in AH
- // =========================
- // 00: success
- // 01: invalid subfunction (AL > 7)
- // 02: invalid input value (out of allowable range)
- // 03: interface error
- // 04: resend command received from mouse controller,
- // device driver should attempt command again
- // 05: cannot enable mouse, since no far call has been installed
- // 80/86: mouse service not implemented
-
- switch (regs.u.r8.al) {
- case 0: // Disable/Enable Mouse
-BX_DEBUG_INT15("case 0:\n");
- switch (regs.u.r8.bh) {
- case 0: // Disable Mouse
-BX_DEBUG_INT15("case 0: disable mouse\n");
- inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- ret = send_to_mouse_ctrl(0xF5); // disable mouse command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data1);
- if ( (ret == 0) || (mouse_data1 == 0xFA) ) {
- CLEAR_CF();
- regs.u.r8.ah = 0;
- return;
- }
- }
-
- // error
- SET_CF();
- regs.u.r8.ah = ret;
- return;
- break;
-
- case 1: // Enable Mouse
-BX_DEBUG_INT15("case 1: enable mouse\n");
- mouse_flags_2 = read_byte(ebda_seg, 0x0027);
- if ( (mouse_flags_2 & 0x80) == 0 ) {
- BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n");
- SET_CF(); // error
- regs.u.r8.ah = 5; // no far call installed
- return;
- }
- inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- ret = send_to_mouse_ctrl(0xF4); // enable mouse command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data1);
- if ( (ret == 0) && (mouse_data1 == 0xFA) ) {
- enable_mouse_int_and_events(); // turn IRQ12 and packet generation on
- CLEAR_CF();
- regs.u.r8.ah = 0;
- return;
- }
- }
- SET_CF();
- regs.u.r8.ah = ret;
- return;
-
- default: // invalid subfunction
- BX_DEBUG_INT15("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh);
- SET_CF(); // error
- regs.u.r8.ah = 1; // invalid subfunction
- return;
- }
- break;
-
- case 1: // Reset Mouse
- case 5: // Initialize Mouse
-BX_DEBUG_INT15("case 1 or 5:\n");
- if (regs.u.r8.al == 5) {
- if (regs.u.r8.bh != 3) {
- SET_CF();
- regs.u.r8.ah = 0x02; // invalid input
- return;
- }
- mouse_flags_2 = read_byte(ebda_seg, 0x0027);
- mouse_flags_2 = (mouse_flags_2 & 0x00) | regs.u.r8.bh;
- mouse_flags_1 = 0x00;
- write_byte(ebda_seg, 0x0026, mouse_flags_1);
- write_byte(ebda_seg, 0x0027, mouse_flags_2);
- }
-
- inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- ret = send_to_mouse_ctrl(0xFF); // reset mouse command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data3);
- // if no mouse attached, it will return RESEND
- if (mouse_data3 == 0xfe) {
- SET_CF();
- return;
- }
- if (mouse_data3 != 0xfa)
- BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3);
- if ( ret == 0 ) {
- ret = get_mouse_data(&mouse_data1);
- if ( ret == 0 ) {
- ret = get_mouse_data(&mouse_data2);
- if ( ret == 0 ) {
- // turn IRQ12 and packet generation on
- enable_mouse_int_and_events();
- CLEAR_CF();
- regs.u.r8.ah = 0;
- regs.u.r8.bl = mouse_data1;
- regs.u.r8.bh = mouse_data2;
- return;
- }
- }
- }
- }
-
- // error
- SET_CF();
- regs.u.r8.ah = ret;
- return;
-
- case 2: // Set Sample Rate
-BX_DEBUG_INT15("case 2:\n");
- switch (regs.u.r8.bh) {
- case 0: mouse_data1 = 10; break; // 10 reports/sec
- case 1: mouse_data1 = 20; break; // 20 reports/sec
- case 2: mouse_data1 = 40; break; // 40 reports/sec
- case 3: mouse_data1 = 60; break; // 60 reports/sec
- case 4: mouse_data1 = 80; break; // 80 reports/sec
- case 5: mouse_data1 = 100; break; // 100 reports/sec (default)
- case 6: mouse_data1 = 200; break; // 200 reports/sec
- default: mouse_data1 = 0;
- }
- if (mouse_data1 > 0) {
- ret = send_to_mouse_ctrl(0xF3); // set sample rate command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data2);
- ret = send_to_mouse_ctrl(mouse_data1);
- ret = get_mouse_data(&mouse_data2);
- CLEAR_CF();
- regs.u.r8.ah = 0;
- } else {
- // error
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- } else {
- // error
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- break;
-
- case 3: // Set Resolution
-BX_DEBUG_INT15("case 3:\n");
- // BH:
- // 0 = 25 dpi, 1 count per millimeter
- // 1 = 50 dpi, 2 counts per millimeter
- // 2 = 100 dpi, 4 counts per millimeter
- // 3 = 200 dpi, 8 counts per millimeter
- comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- if (regs.u.r8.bh < 4) {
- ret = send_to_mouse_ctrl(0xE8); // set resolution command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data1);
- if (mouse_data1 != 0xfa)
- BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
- ret = send_to_mouse_ctrl(regs.u.r8.bh);
- ret = get_mouse_data(&mouse_data1);
- if (mouse_data1 != 0xfa)
- BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
- CLEAR_CF();
- regs.u.r8.ah = 0;
- } else {
- // error
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- } else {
- // error
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
- break;
-
- case 4: // Get Device ID
-BX_DEBUG_INT15("case 4:\n");
- inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- ret = send_to_mouse_ctrl(0xF2); // get mouse ID command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data1);
- ret = get_mouse_data(&mouse_data2);
- CLEAR_CF();
- regs.u.r8.ah = 0;
- regs.u.r8.bh = mouse_data2;
- } else {
- // error
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- break;
-
- case 6: // Return Status & Set Scaling Factor...
-BX_DEBUG_INT15("case 6:\n");
- switch (regs.u.r8.bh) {
- case 0: // Return Status
- comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- ret = send_to_mouse_ctrl(0xE9); // get mouse info command
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data1);
- if (mouse_data1 != 0xfa)
- BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
- if (ret == 0) {
- ret = get_mouse_data(&mouse_data1);
- if ( ret == 0 ) {
- ret = get_mouse_data(&mouse_data2);
- if ( ret == 0 ) {
- ret = get_mouse_data(&mouse_data3);
- if ( ret == 0 ) {
- CLEAR_CF();
- regs.u.r8.ah = 0;
- regs.u.r8.bl = mouse_data1;
- regs.u.r8.cl = mouse_data2;
- regs.u.r8.dl = mouse_data3;
- set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
- return;
- }
- }
- }
- }
- }
-
- // error
- SET_CF();
- regs.u.r8.ah = ret;
- set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
- return;
-
- case 1: // Set Scaling Factor to 1:1
- case 2: // Set Scaling Factor to 2:1
- comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- if (regs.u.r8.bh == 1) {
- ret = send_to_mouse_ctrl(0xE6);
- } else {
- ret = send_to_mouse_ctrl(0xE7);
- }
- if (ret == 0) {
- get_mouse_data(&mouse_data1);
- ret = (mouse_data1 != 0xFA);
- }
- if (ret == 0) {
- CLEAR_CF();
- regs.u.r8.ah = 0;
- } else {
- // error
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- }
- set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
- break;
-
- default:
- BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh);
- }
- break;
-
- case 7: // Set Mouse Handler Address
-BX_DEBUG_INT15("case 7:\n");
- mouse_driver_seg = ES;
- mouse_driver_offset = regs.u.r16.bx;
- write_word(ebda_seg, 0x0022, mouse_driver_offset);
- write_word(ebda_seg, 0x0024, mouse_driver_seg);
- mouse_flags_2 = read_byte(ebda_seg, 0x0027);
- if (mouse_driver_offset == 0 && mouse_driver_seg == 0) {
- /* remove handler */
- if ( (mouse_flags_2 & 0x80) != 0 ) {
- mouse_flags_2 &= ~0x80;
- inhibit_mouse_int_and_events(); // disable IRQ12 and packets
- }
- }
- else {
- /* install handler */
- mouse_flags_2 |= 0x80;
- }
- write_byte(ebda_seg, 0x0027, mouse_flags_2);
- CLEAR_CF();
- regs.u.r8.ah = 0;
- break;
-
- default:
-BX_DEBUG_INT15("case default:\n");
- regs.u.r8.ah = 1; // invalid function
- SET_CF();
- }
- break;
-
- default:
- BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
- (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
- }
-}
-#endif // BX_USE_PS2_MOUSE
-
-
-void set_e820_range(ES, DI, start, end, extra_start, extra_end, type)
- Bit16u ES;
- Bit16u DI;
- Bit32u start;
- Bit32u end;
- Bit8u extra_start;
- Bit8u extra_end;
- Bit16u type;
-{
- write_word(ES, DI, start);
- write_word(ES, DI+2, start >> 16);
- write_word(ES, DI+4, extra_start);
- write_word(ES, DI+6, 0x00);
-
- end -= start;
- extra_end -= extra_start;
- write_word(ES, DI+8, end);
- write_word(ES, DI+10, end >> 16);
- write_word(ES, DI+12, extra_end);
- write_word(ES, DI+14, 0x0000);
-
- write_word(ES, DI+16, type);
- write_word(ES, DI+18, 0x0);
-}
-
- void
-int15_function32(regs, ES, DS, FLAGS)
- pushad_regs_t regs; // REGS pushed via pushad
- Bit16u ES, DS, FLAGS;
-{
- Bit32u extended_memory_size=0; // 64bits long
- Bit32u extra_lowbits_memory_size=0;
- Bit16u CX,DX;
- Bit8u extra_highbits_memory_size=0;
-
-BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
-
- switch (regs.u.r8.ah) {
- case 0x86:
- // Wait for CX:DX microseconds. currently using the
- // refresh request port 0x61 bit4, toggling every 15usec
-
- CX = regs.u.r16.cx;
- DX = regs.u.r16.dx;
-
-ASM_START
- sti
-
- ;; Get the count in eax
- mov bx, sp
- SEG SS
- mov ax, _int15_function32.CX [bx]
- shl eax, #16
- SEG SS
- mov ax, _int15_function32.DX [bx]
-
- ;; convert to numbers of 15usec ticks
- mov ebx, #15
- xor edx, edx
- div eax, ebx
- mov ecx, eax
-
- ;; wait for ecx number of refresh requests
- in al, #0x61
- and al,#0x10
- mov ah, al
-
- or ecx, ecx
- je int1586_tick_end
-int1586_tick:
- in al, #0x61
- and al,#0x10
- cmp al, ah
- je int1586_tick
- mov ah, al
- dec ecx
- jnz int1586_tick
-int1586_tick_end:
-ASM_END
-
- break;
-
- case 0xe8:
- switch(regs.u.r8.al)
- {
- case 0x20: // coded by osmaker aka K.J.
- if(regs.u.r32.edx == 0x534D4150)
- {
- extended_memory_size = inb_cmos(0x35);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x34);
- extended_memory_size *= 64;
- // greater than EFF00000???
- if(extended_memory_size > 0x3bc000) {
- extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
- }
- extended_memory_size *= 1024;
- extended_memory_size += (16L * 1024 * 1024);
-
- if(extended_memory_size <= (16L * 1024 * 1024)) {
- extended_memory_size = inb_cmos(0x31);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x30);
- extended_memory_size *= 1024;
- extended_memory_size += (1L * 1024 * 1024);
- }
-
- extra_lowbits_memory_size = inb_cmos(0x5c);
- extra_lowbits_memory_size <<= 8;
- extra_lowbits_memory_size |= inb_cmos(0x5b);
- extra_lowbits_memory_size *= 64;
- extra_lowbits_memory_size *= 1024;
- extra_highbits_memory_size = inb_cmos(0x5d);
-
- switch(regs.u.r16.bx)
- {
- case 0:
- set_e820_range(ES, regs.u.r16.di,
- 0x0000000L, 0x0009f000L, 0, 0, 1);
- regs.u.r32.ebx = 1;
- break;
- case 1:
- set_e820_range(ES, regs.u.r16.di,
- 0x0009f000L, 0x000a0000L, 0, 0, 2);
- regs.u.r32.ebx = 2;
- break;
- case 2:
- set_e820_range(ES, regs.u.r16.di,
- 0x000e8000L, 0x00100000L, 0, 0, 2);
- regs.u.r32.ebx = 3;
- break;
- case 3:
-#if BX_ROMBIOS32
- set_e820_range(ES, regs.u.r16.di,
- 0x00100000L,
- extended_memory_size - ACPI_DATA_SIZE ,0, 0, 1);
- regs.u.r32.ebx = 4;
-#else
- set_e820_range(ES, regs.u.r16.di,
- 0x00100000L,
- extended_memory_size, 1);
- regs.u.r32.ebx = 5;
-#endif
- break;
- case 4:
- set_e820_range(ES, regs.u.r16.di,
- extended_memory_size - ACPI_DATA_SIZE,
- extended_memory_size ,0, 0, 3); // ACPI RAM
- regs.u.r32.ebx = 5;
- break;
- case 5:
- /* 4 pages before the bios, 3 pages for vmx tss pages,
- * the other page for EPT real mode pagetable */
- set_e820_range(ES, regs.u.r16.di, 0xfeffc000L,
- 0xff000000L, 0, 0, 2);
- regs.u.r32.ebx = 6;
- break;
- case 6:
- /* 16MB BIOS area at the end of 4 GB */
- set_e820_range(ES, regs.u.r16.di,
- 0xff000000L, 0x00000000L ,0, 0, 2);
- if (extra_highbits_memory_size || extra_lowbits_memory_size)
- regs.u.r32.ebx = 7;
- else
- regs.u.r32.ebx = 0;
- break;
- case 7:
- /* Maping of memory above 4 GB */
- set_e820_range(ES, regs.u.r16.di, 0x00000000L,
- extra_lowbits_memory_size, 1, extra_highbits_memory_size
- + 1, 1);
- regs.u.r32.ebx = 0;
- break;
- default: /* AX=E820, DX=534D4150, BX unrecognized */
- goto int15_unimplemented;
- break;
- }
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- } else {
- // if DX != 0x534D4150)
- goto int15_unimplemented;
- }
- break;
-
- case 0x01:
- // do we have any reason to fail here ?
- CLEAR_CF();
-
- // my real system sets ax and bx to 0
- // this is confirmed by Ralph Brown list
- // but syslinux v1.48 is known to behave
- // strangely if ax is set to 0
- // regs.u.r16.ax = 0;
- // regs.u.r16.bx = 0;
-
- // Get the amount of extended memory (above 1M)
- regs.u.r8.cl = inb_cmos(0x30);
- regs.u.r8.ch = inb_cmos(0x31);
-
- // limit to 15M
- if(regs.u.r16.cx > 0x3c00)
- {
- regs.u.r16.cx = 0x3c00;
- }
-
- // Get the amount of extended memory above 16M in 64k blocs
- regs.u.r8.dl = inb_cmos(0x34);
- regs.u.r8.dh = inb_cmos(0x35);
-
- // Set configured memory equal to extended memory
- regs.u.r16.ax = regs.u.r16.cx;
- regs.u.r16.bx = regs.u.r16.dx;
- break;
- default: /* AH=0xE8?? but not implemented */
- goto int15_unimplemented;
- }
- break;
- int15_unimplemented:
- // fall into the default
- default:
- BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
- (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
- SET_CF();
- regs.u.r8.ah = UNSUPPORTED_FUNCTION;
- break;
- }
-}
-
- void
-int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS;
-{
- Bit8u scan_code, ascii_code, shift_flags, led_flags, count;
- Bit16u kbd_code, max;
-
- BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
-
- shift_flags = read_byte(0x0040, 0x17);
- led_flags = read_byte(0x0040, 0x97);
- if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) {
-ASM_START
- cli
-ASM_END
- outb(0x60, 0xed);
- while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
- if ((inb(0x60) == 0xfa)) {
- led_flags &= 0xf8;
- led_flags |= ((shift_flags >> 4) & 0x07);
- outb(0x60, led_flags & 0x07);
- while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
- inb(0x60);
- write_byte(0x0040, 0x97, led_flags);
- }
-ASM_START
- sti
-ASM_END
- }
-
- switch (GET_AH()) {
- case 0x00: /* read keyboard input */
-
- if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
- BX_PANIC("KBD: int16h: out of keyboard input\n");
- }
- if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
- else if (ascii_code == 0xE0) ascii_code = 0;
- AX = (scan_code << 8) | ascii_code;
- break;
-
- case 0x01: /* check keyboard status */
- if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
- SET_ZF();
- return;
- }
- if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
- else if (ascii_code == 0xE0) ascii_code = 0;
- AX = (scan_code << 8) | ascii_code;
- CLEAR_ZF();
- break;
-
- case 0x02: /* get shift flag status */
- shift_flags = read_byte(0x0040, 0x17);
- SET_AL(shift_flags);
- break;
-
- case 0x05: /* store key-stroke into buffer */
- if ( !enqueue_key(GET_CH(), GET_CL()) ) {
- SET_AL(1);
- }
- else {
- SET_AL(0);
- }
- break;
-
- case 0x09: /* GET KEYBOARD FUNCTIONALITY */
- // bit Bochs Description
- // 7 0 reserved
- // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support)
- // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support)
- // 4 1 INT 16/AH=0Ah supported
- // 3 0 INT 16/AX=0306h supported
- // 2 0 INT 16/AX=0305h supported
- // 1 0 INT 16/AX=0304h supported
- // 0 0 INT 16/AX=0300h supported
- //
- SET_AL(0x30);
- break;
-
- case 0x0A: /* GET KEYBOARD ID */
- count = 2;
- kbd_code = 0x0;
- outb(0x60, 0xf2);
- /* Wait for data */
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00);
- if (max>0x0) {
- if ((inb(0x60) == 0xfa)) {
- do {
- max=0xffff;
- while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00);
- if (max>0x0) {
- kbd_code >>= 8;
- kbd_code |= (inb(0x60) << 8);
- }
- } while (--count>0);
- }
- }
- BX=kbd_code;
- break;
-
- case 0x10: /* read MF-II keyboard input */
-
- if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
- BX_PANIC("KBD: int16h: out of keyboard input\n");
- }
- if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
- AX = (scan_code << 8) | ascii_code;
- break;
-
- case 0x11: /* check MF-II keyboard status */
- if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
- SET_ZF();
- return;
- }
- if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
- AX = (scan_code << 8) | ascii_code;
- CLEAR_ZF();
- break;
-
- case 0x12: /* get extended keyboard status */
- shift_flags = read_byte(0x0040, 0x17);
- SET_AL(shift_flags);
- shift_flags = read_byte(0x0040, 0x18) & 0x73;
- shift_flags |= read_byte(0x0040, 0x96) & 0x0c;
- SET_AH(shift_flags);
- BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX);
- break;
-
- case 0x92: /* keyboard capability check called by DOS 5.0+ keyb */
- SET_AH(0x80); // function int16 ah=0x10-0x12 supported
- break;
-
- case 0xA2: /* 122 keys capability check called by DOS 5.0+ keyb */
- // don't change AH : function int16 ah=0x20-0x22 NOT supported
- break;
-
- case 0x6F:
- if (GET_AL() == 0x08)
- SET_AH(0x02); // unsupported, aka normal keyboard
-
- default:
- BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
- }
-}
-
- unsigned int
-dequeue_key(scan_code, ascii_code, incr)
- Bit8u *scan_code;
- Bit8u *ascii_code;
- unsigned int incr;
-{
- Bit16u buffer_start, buffer_end, buffer_head, buffer_tail;
- Bit16u ss;
- Bit8u acode, scode;
-
-#if BX_CPU < 2
- buffer_start = 0x001E;
- buffer_end = 0x003E;
-#else
- buffer_start = read_word(0x0040, 0x0080);
- buffer_end = read_word(0x0040, 0x0082);
-#endif
-
- buffer_head = read_word(0x0040, 0x001a);
- buffer_tail = read_word(0x0040, 0x001c);
-
- if (buffer_head != buffer_tail) {
- ss = get_SS();
- acode = read_byte(0x0040, buffer_head);
- scode = read_byte(0x0040, buffer_head+1);
- write_byte(ss, ascii_code, acode);
- write_byte(ss, scan_code, scode);
-
- if (incr) {
- buffer_head += 2;
- if (buffer_head >= buffer_end)
- buffer_head = buffer_start;
- write_word(0x0040, 0x001a, buffer_head);
- }
- return(1);
- }
- else {
- return(0);
- }
-}
-
-static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n";
-
- Bit8u
-inhibit_mouse_int_and_events()
-{
- Bit8u command_byte, prev_command_byte;
-
- // Turn off IRQ generation and aux data line
- if ( inb(0x64) & 0x02 )
- BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse");
- outb(0x64, 0x20); // get command byte
- while ( (inb(0x64) & 0x01) != 0x01 );
- prev_command_byte = inb(0x60);
- command_byte = prev_command_byte;
- //while ( (inb(0x64) & 0x02) );
- if ( inb(0x64) & 0x02 )
- BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse");
- command_byte &= 0xfd; // turn off IRQ 12 generation
- command_byte |= 0x20; // disable mouse serial clock line
- outb(0x64, 0x60); // write command byte
- outb(0x60, command_byte);
- return(prev_command_byte);
-}
-
- void
-enable_mouse_int_and_events()
-{
- Bit8u command_byte;
-
- // Turn on IRQ generation and aux data line
- if ( inb(0x64) & 0x02 )
- BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse");
- outb(0x64, 0x20); // get command byte
- while ( (inb(0x64) & 0x01) != 0x01 );
- command_byte = inb(0x60);
- //while ( (inb(0x64) & 0x02) );
- if ( inb(0x64) & 0x02 )
- BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse");
- command_byte |= 0x02; // turn on IRQ 12 generation
- command_byte &= 0xdf; // enable mouse serial clock line
- outb(0x64, 0x60); // write command byte
- outb(0x60, command_byte);
-}
-
- Bit8u
-send_to_mouse_ctrl(sendbyte)
- Bit8u sendbyte;
-{
- Bit8u response;
-
- // wait for chance to write to ctrl
- if ( inb(0x64) & 0x02 )
- BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse");
- outb(0x64, 0xD4);
- outb(0x60, sendbyte);
- return(0);
-}
-
-
- Bit8u
-get_mouse_data(data)
- Bit8u *data;
-{
- Bit8u response;
- Bit16u ss;
-
- while ( (inb(0x64) & 0x21) != 0x21 ) {
- }
-
- response = inb(0x60);
-
- ss = get_SS();
- write_byte(ss, data, response);
- return(0);
-}
-
- void
-set_kbd_command_byte(command_byte)
- Bit8u command_byte;
-{
- if ( inb(0x64) & 0x02 )
- BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm");
- outb(0x64, 0xD4);
-
- outb(0x64, 0x60); // write command byte
- outb(0x60, command_byte);
-}
-
- void
-int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX;
-{
- Bit8u scancode, asciicode, shift_flags;
- Bit8u mf2_flags, mf2_state;
-
- //
- // DS has been set to F000 before call
- //
-
-
- scancode = GET_AL();
-
- if (scancode == 0) {
- BX_INFO("KBD: int09 handler: AL=0\n");
- return;
- }
-
-
- shift_flags = read_byte(0x0040, 0x17);
- mf2_flags = read_byte(0x0040, 0x18);
- mf2_state = read_byte(0x0040, 0x96);
- asciicode = 0;
-
- switch (scancode) {
- case 0x3a: /* Caps Lock press */
- shift_flags ^= 0x40;
- write_byte(0x0040, 0x17, shift_flags);
- mf2_flags |= 0x40;
- write_byte(0x0040, 0x18, mf2_flags);
- break;
- case 0xba: /* Caps Lock release */
- mf2_flags &= ~0x40;
- write_byte(0x0040, 0x18, mf2_flags);
- break;
-
- case 0x2a: /* L Shift press */
- shift_flags |= 0x02;
- write_byte(0x0040, 0x17, shift_flags);
- break;
- case 0xaa: /* L Shift release */
- shift_flags &= ~0x02;
- write_byte(0x0040, 0x17, shift_flags);
- break;
-
- case 0x36: /* R Shift press */
- shift_flags |= 0x01;
- write_byte(0x0040, 0x17, shift_flags);
- break;
- case 0xb6: /* R Shift release */
- shift_flags &= ~0x01;
- write_byte(0x0040, 0x17, shift_flags);
- break;
-
- case 0x1d: /* Ctrl press */
- if ((mf2_state & 0x01) == 0) {
- shift_flags |= 0x04;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x02) {
- mf2_state |= 0x04;
- write_byte(0x0040, 0x96, mf2_state);
- } else {
- mf2_flags |= 0x01;
- write_byte(0x0040, 0x18, mf2_flags);
- }
- }
- break;
- case 0x9d: /* Ctrl release */
- if ((mf2_state & 0x01) == 0) {
- shift_flags &= ~0x04;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x02) {
- mf2_state &= ~0x04;
- write_byte(0x0040, 0x96, mf2_state);
- } else {
- mf2_flags &= ~0x01;
- write_byte(0x0040, 0x18, mf2_flags);
- }
- }
- break;
-
- case 0x38: /* Alt press */
- shift_flags |= 0x08;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x02) {
- mf2_state |= 0x08;
- write_byte(0x0040, 0x96, mf2_state);
- } else {
- mf2_flags |= 0x02;
- write_byte(0x0040, 0x18, mf2_flags);
- }
- break;
- case 0xb8: /* Alt release */
- shift_flags &= ~0x08;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x02) {
- mf2_state &= ~0x08;
- write_byte(0x0040, 0x96, mf2_state);
- } else {
- mf2_flags &= ~0x02;
- write_byte(0x0040, 0x18, mf2_flags);
- }
- break;
-
- case 0x45: /* Num Lock press */
- if ((mf2_state & 0x03) == 0) {
- mf2_flags |= 0x20;
- write_byte(0x0040, 0x18, mf2_flags);
- shift_flags ^= 0x20;
- write_byte(0x0040, 0x17, shift_flags);
- }
- break;
- case 0xc5: /* Num Lock release */
- if ((mf2_state & 0x03) == 0) {
- mf2_flags &= ~0x20;
- write_byte(0x0040, 0x18, mf2_flags);
- }
- break;
-
- case 0x46: /* Scroll Lock press */
- mf2_flags |= 0x10;
- write_byte(0x0040, 0x18, mf2_flags);
- shift_flags ^= 0x10;
- write_byte(0x0040, 0x17, shift_flags);
- break;
-
- case 0xc6: /* Scroll Lock release */
- mf2_flags &= ~0x10;
- write_byte(0x0040, 0x18, mf2_flags);
- break;
-
- default:
- if (scancode & 0x80) {
- break; /* toss key releases ... */
- }
- if (scancode > MAX_SCAN_CODE) {
- BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode);
- return;
- }
- if (shift_flags & 0x08) { /* ALT */
- asciicode = scan_to_scanascii[scancode].alt;
- scancode = scan_to_scanascii[scancode].alt >> 8;
- } else if (shift_flags & 0x04) { /* CONTROL */
- asciicode = scan_to_scanascii[scancode].control;
- scancode = scan_to_scanascii[scancode].control >> 8;
- } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) {
- /* extended keys handling */
- asciicode = 0xe0;
- scancode = scan_to_scanascii[scancode].normal >> 8;
- } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
- /* check if lock state should be ignored
- * because a SHIFT key are pressed */
-
- if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
- asciicode = scan_to_scanascii[scancode].normal;
- scancode = scan_to_scanascii[scancode].normal >> 8;
- } else {
- asciicode = scan_to_scanascii[scancode].shift;
- scancode = scan_to_scanascii[scancode].shift >> 8;
- }
- } else {
- /* check if lock is on */
- if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
- asciicode = scan_to_scanascii[scancode].shift;
- scancode = scan_to_scanascii[scancode].shift >> 8;
- } else {
- asciicode = scan_to_scanascii[scancode].normal;
- scancode = scan_to_scanascii[scancode].normal >> 8;
- }
- }
- if (scancode==0 && asciicode==0) {
- BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n");
- }
- enqueue_key(scancode, asciicode);
- break;
- }
- if ((scancode & 0x7f) != 0x1d) {
- mf2_state &= ~0x01;
- }
- mf2_state &= ~0x02;
- write_byte(0x0040, 0x96, mf2_state);
-}
-
- unsigned int
-enqueue_key(scan_code, ascii_code)
- Bit8u scan_code, ascii_code;
-{
- Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail;
-
-#if BX_CPU < 2
- buffer_start = 0x001E;
- buffer_end = 0x003E;
-#else
- buffer_start = read_word(0x0040, 0x0080);
- buffer_end = read_word(0x0040, 0x0082);
-#endif
-
- buffer_head = read_word(0x0040, 0x001A);
- buffer_tail = read_word(0x0040, 0x001C);
-
- temp_tail = buffer_tail;
- buffer_tail += 2;
- if (buffer_tail >= buffer_end)
- buffer_tail = buffer_start;
-
- if (buffer_tail == buffer_head) {
- return(0);
- }
-
- write_byte(0x0040, temp_tail, ascii_code);
- write_byte(0x0040, temp_tail+1, scan_code);
- write_word(0x0040, 0x001C, buffer_tail);
- return(1);
-}
-
-
- void
-int74_function(make_farcall, Z, Y, X, status)
- Bit16u make_farcall, Z, Y, X, status;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u in_byte, index, package_count;
- Bit8u mouse_flags_1, mouse_flags_2;
-
-BX_DEBUG_INT74("entering int74_function\n");
- make_farcall = 0;
-
- in_byte = inb(0x64);
- if ( (in_byte & 0x21) != 0x21 ) {
- return;
- }
- in_byte = inb(0x60);
-BX_DEBUG_INT74("int74: read byte %02x\n", in_byte);
-
- mouse_flags_1 = read_byte(ebda_seg, 0x0026);
- mouse_flags_2 = read_byte(ebda_seg, 0x0027);
-
- if ( (mouse_flags_2 & 0x80) != 0x80 ) {
- return;
- }
-
- package_count = mouse_flags_2 & 0x07;
- index = mouse_flags_1 & 0x07;
- write_byte(ebda_seg, 0x28 + index, in_byte);
-
- if ( (index+1) >= package_count ) {
-BX_DEBUG_INT74("int74_function: make_farcall=1\n");
- status = read_byte(ebda_seg, 0x0028 + 0);
- X = read_byte(ebda_seg, 0x0028 + 1);
- Y = read_byte(ebda_seg, 0x0028 + 2);
- Z = 0;
- mouse_flags_1 = 0;
- // check if far call handler installed
- if (mouse_flags_2 & 0x80)
- make_farcall = 1;
- }
- else {
- mouse_flags_1++;
- }
- write_byte(ebda_seg, 0x0026, mouse_flags_1);
-}
-
-#define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
-
-#if BX_USE_ATADRV
-
- void
-int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit32u lba_low, lba_high;
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u cylinder, head, sector;
- Bit16u segment, offset;
- Bit16u npc, nph, npspt, nlc, nlh, nlspt;
- Bit16u size, count;
- Bit8u device, status;
-
- BX_DEBUG_INT13_HD("int13_harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
-
- write_byte(0x0040, 0x008e, 0); // clear completion flag
-
- // basic check : device has to be defined
- if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) {
- BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
- goto int13_fail;
- }
-
- // Get the ata channel
- device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
-
- // basic check : device has to be valid
- if (device >= BX_MAX_ATA_DEVICES) {
- BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
- goto int13_fail;
- }
-
- switch (GET_AH()) {
-
- case 0x00: /* disk controller reset */
- ata_reset (device);
- goto int13_success;
- break;
-
- case 0x01: /* read disk status */
- status = read_byte(0x0040, 0x0074);
- SET_AH(status);
- SET_DISK_RET_STATUS(0);
- /* set CF if error status read */
- if (status) goto int13_fail_nostatus;
- else goto int13_success_noah;
- break;
-
- case 0x02: // read disk sectors
- case 0x03: // write disk sectors
- case 0x04: // verify disk sectors
-
- count = GET_AL();
- cylinder = GET_CH();
- cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300;
- sector = (GET_CL() & 0x3f);
- head = GET_DH();
-
- segment = ES;
- offset = BX;
-
- if ((count > 128) || (count == 0) || (sector == 0)) {
- BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH());
- goto int13_fail;
- }
-
- nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
- nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
- nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
-
- // sanity check on cyl heads, sec
- if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) {
- BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector);
- goto int13_fail;
- }
-
- // FIXME verify
- if ( GET_AH() == 0x04 ) goto int13_success;
-
- nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
- npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
-
- // if needed, translate lchs to lba, and execute command
- if ( (nph != nlh) || (npspt != nlspt)) {
- lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
- lba_high = 0;
- sector = 0; // this forces the command to be lba
- }
-
- if ( GET_AH() == 0x02 )
- status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
- else
- status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
-
- // Set nb of sector transferred
- SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
-
- if (status != 0) {
- BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
- SET_AH(0x0c);
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x05: /* format disk track */
- BX_INFO("format disk track called\n");
- goto int13_success;
- return;
- break;
-
- case 0x08: /* read disk drive parameters */
-
- // Get logical geometry from table
- nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
- nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
- nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
- count = read_byte(ebda_seg, &EbdaData->ata.hdcount);
-
- nlc = nlc - 2; /* 0 based , last sector not used */
- SET_AL(0);
- SET_CH(nlc & 0xff);
- SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f));
- SET_DH(nlh - 1);
- SET_DL(count); /* FIXME returns 0, 1, or n hard drives */
-
- // FIXME should set ES & DI
-
- goto int13_success;
- break;
-
- case 0x10: /* check drive ready */
- // should look at 40:8E also???
-
- // Read the status from controller
- status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT);
- if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) {
- goto int13_success;
- }
- else {
- SET_AH(0xAA);
- goto int13_fail_noah;
- }
- break;
-
- case 0x15: /* read disk drive size */
-
- // Get logical geometry from table
- nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
- nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
- nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
-
- // Compute sector count seen by int13
- lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt;
- CX = lba_low >> 16;
- DX = lba_low & 0xffff;
-
- SET_AH(3); // hard disk accessible
- goto int13_success_noah;
- break;
-
- case 0x41: // IBM/MS installation check
- BX=0xaa55; // install check
- SET_AH(0x30); // EDD 3.0
- CX=0x0007; // ext disk access and edd, removable supported
- goto int13_success_noah;
- break;
-
- case 0x42: // IBM/MS extended read
- case 0x43: // IBM/MS extended write
- case 0x44: // IBM/MS verify
- case 0x47: // IBM/MS extended seek
-
- count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
- segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
- offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
-
- // Get 32 msb lba and check
- lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
- if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) {
- BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
- goto int13_fail;
- }
-
- // Get 32 lsb lba and check
- lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
- if (lba_high == read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high)
- && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) {
- BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
- goto int13_fail;
- }
-
- // If verify or seek
- if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
- goto int13_success;
-
- // Execute the command
- if ( GET_AH() == 0x42 )
- status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
- else
- status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
-
- count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
- write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
-
- if (status != 0) {
- BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
- SET_AH(0x0c);
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x45: // IBM/MS lock/unlock drive
- case 0x49: // IBM/MS extended media change
- goto int13_success; // Always success for HD
- break;
-
- case 0x46: // IBM/MS eject media
- SET_AH(0xb2); // Volume Not Removable
- goto int13_fail_noah; // Always fail for HD
- break;
-
- case 0x48: // IBM/MS get drive parameters
- size=read_word(DS,SI+(Bit16u)&Int13DPT->size);
-
- // Buffer is too small
- if(size < 0x1a)
- goto int13_fail;
-
- // EDD 1.x
- if(size >= 0x1a) {
- Bit16u blksize;
-
- npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders);
- nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
- npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
- lba_low = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low);
- lba_high = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high);
- blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
- if (lba_high || (lba_low/npspt)/nph > 0x3fff)
- {
- write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is invalid
- write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff);
- }
- else
- {
- write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
- write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
- }
- write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
- write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low);
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high);
- write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
- }
-
- // EDD 2.x
- if(size >= 0x1e) {
- Bit8u channel, dev, irq, mode, checksum, i, translation;
- Bit16u iobase1, iobase2, options;
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
- write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
-
- // Fill in dpte
- channel = device / 2;
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
- irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
- mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
- translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation);
-
- options = (translation==ATA_TRANSLATION_NONE?0:1)<<3; // chs translation
- options |= (1<<4); // lba translation
- options |= (mode==ATA_MODE_PIO32?1:0)<<7;
- options |= (translation==ATA_TRANSLATION_LBA?1:0)<<9;
- options |= (translation==ATA_TRANSLATION_RECHS?3:0)<<9;
-
- write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
- write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
- write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
- write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
- write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
- write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
- write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
- if (size >=0x42)
- write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
- else
- write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10);
-
- checksum=0;
- for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
- checksum = ~checksum;
- write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
- }
-
- // EDD 3.x
- if(size >= 0x42) {
- Bit8u channel, iface, checksum, i;
- Bit16u iobase1;
-
- channel = device / 2;
- iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
- write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
- write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
- write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
- write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
-
- if (iface==ATA_IFACE_ISA) {
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
- }
- else {
- // FIXME PCI
- }
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
-
- if (iface==ATA_IFACE_ISA) {
- write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
- write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
- write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
- }
- else {
- // FIXME PCI
- }
- write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
- write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
- write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
- write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
-
- checksum=0;
- for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
- checksum = ~checksum;
- write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
- }
-
- goto int13_success;
- break;
-
- case 0x4e: // // IBM/MS set hardware configuration
- // DMA, prefetch, PIO maximum not supported
- switch (GET_AL()) {
- case 0x01:
- case 0x03:
- case 0x04:
- case 0x06:
- goto int13_success;
- break;
- default :
- goto int13_fail;
- }
- break;
-
- case 0x09: /* initialize drive parameters */
- case 0x0c: /* seek to specified cylinder */
- case 0x0d: /* alternate disk reset */
- case 0x11: /* recalibrate */
- case 0x14: /* controller internal diagnostic */
- BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH());
- goto int13_success;
- break;
-
- case 0x0a: /* read disk sectors with ECC */
- case 0x0b: /* write disk sectors with ECC */
- case 0x18: // set media type for format
- case 0x50: // IBM/MS send packet command
- default:
- BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
- goto int13_fail;
- break;
- }
-
-int13_fail:
- SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
-int13_fail_noah:
- SET_DISK_RET_STATUS(GET_AH());
-int13_fail_nostatus:
- SET_CF(); // error occurred
- return;
-
-int13_success:
- SET_AH(0x00); // no error
-int13_success_noah:
- SET_DISK_RET_STATUS(0x00);
- CLEAR_CF(); // no error
- return;
-}
-
-// ---------------------------------------------------------------------------
-// Start of int13 for cdrom
-// ---------------------------------------------------------------------------
-
- void
-int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u device, status, locks;
- Bit8u atacmd[12];
- Bit32u lba;
- Bit16u count, segment, offset, i, size;
-
- BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
-
- SET_DISK_RET_STATUS(0x00);
-
- /* basic check : device should be 0xE0+ */
- if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
- BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
- goto int13_fail;
- }
-
- // Get the ata channel
- device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
-
- /* basic check : device has to be valid */
- if (device >= BX_MAX_ATA_DEVICES) {
- BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
- goto int13_fail;
- }
-
- switch (GET_AH()) {
-
- // all those functions return SUCCESS
- case 0x00: /* disk controller reset */
- case 0x09: /* initialize drive parameters */
- case 0x0c: /* seek to specified cylinder */
- case 0x0d: /* alternate disk reset */
- case 0x10: /* check drive ready */
- case 0x11: /* recalibrate */
- case 0x14: /* controller internal diagnostic */
- case 0x16: /* detect disk change */
- goto int13_success;
- break;
-
- // all those functions return disk write-protected
- case 0x03: /* write disk sectors */
- case 0x05: /* format disk track */
- case 0x43: // IBM/MS extended write
- SET_AH(0x03);
- goto int13_fail_noah;
- break;
-
- case 0x01: /* read disk status */
- status = read_byte(0x0040, 0x0074);
- SET_AH(status);
- SET_DISK_RET_STATUS(0);
-
- /* set CF if error status read */
- if (status) goto int13_fail_nostatus;
- else goto int13_success_noah;
- break;
-
- case 0x15: /* read disk drive size */
- SET_AH(0x02);
- goto int13_fail_noah;
- break;
-
- case 0x41: // IBM/MS installation check
- BX=0xaa55; // install check
- SET_AH(0x30); // EDD 2.1
- CX=0x0007; // ext disk access, removable and edd
- goto int13_success_noah;
- break;
-
- case 0x42: // IBM/MS extended read
- case 0x44: // IBM/MS verify sectors
- case 0x47: // IBM/MS extended seek
-
- count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
- segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
- offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
-
- // Can't use 64 bits lba
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
- if (lba != 0L) {
- BX_PANIC("int13_cdrom: function %02x. Can't use 64bits lba\n",GET_AH());
- goto int13_fail;
- }
-
- // Get 32 bits lba
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
-
- // If verify or seek
- if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
- goto int13_success;
-
- memsetb(get_SS(),atacmd,0,12);
- atacmd[0]=0x28; // READ command
- atacmd[7]=(count & 0xff00) >> 8; // Sectors
- atacmd[8]=(count & 0x00ff); // Sectors
- atacmd[2]=(lba & 0xff000000) >> 24; // LBA
- atacmd[3]=(lba & 0x00ff0000) >> 16;
- atacmd[4]=(lba & 0x0000ff00) >> 8;
- atacmd[5]=(lba & 0x000000ff);
- status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset);
-
- count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
- write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
-
- if (status != 0) {
- BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
- SET_AH(0x0c);
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x45: // IBM/MS lock/unlock drive
- if (GET_AL() > 2) goto int13_fail;
-
- locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
-
- switch (GET_AL()) {
- case 0 : // lock
- if (locks == 0xff) {
- SET_AH(0xb4);
- SET_AL(1);
- goto int13_fail_noah;
- }
- write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
- SET_AL(1);
- break;
- case 1 : // unlock
- if (locks == 0x00) {
- SET_AH(0xb0);
- SET_AL(0);
- goto int13_fail_noah;
- }
- write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
- SET_AL(locks==0?0:1);
- break;
- case 2 : // status
- SET_AL(locks==0?0:1);
- break;
- }
- goto int13_success;
- break;
-
- case 0x46: // IBM/MS eject media
- locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
-
- if (locks != 0) {
- SET_AH(0xb1); // media locked
- goto int13_fail_noah;
- }
- // FIXME should handle 0x31 no media in device
- // FIXME should handle 0xb5 valid request failed
-
- // Call removable media eject
- ASM_START
- push bp
- mov bp, sp
-
- mov ah, #0x52
- int #0x15
- mov _int13_cdrom.status + 2[bp], ah
- jnc int13_cdrom_rme_end
- mov _int13_cdrom.status, #1
-int13_cdrom_rme_end:
- pop bp
- ASM_END
-
- if (status != 0) {
- SET_AH(0xb1); // media locked
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x48: // IBM/MS get drive parameters
- size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
-
- // Buffer is too small
- if(size < 0x1a)
- goto int13_fail;
-
- // EDD 1.x
- if(size >= 0x1a) {
- Bit16u cylinders, heads, spt, blksize;
-
- blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
- write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media change, lockable, max values
- write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff);
- write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
- write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); // FIXME should be Bit64
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
- write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
- }
-
- // EDD 2.x
- if(size >= 0x1e) {
- Bit8u channel, dev, irq, mode, checksum, i;
- Bit16u iobase1, iobase2, options;
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
- write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
-
- // Fill in dpte
- channel = device / 2;
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
- irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
- mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
-
- // FIXME atapi device
- options = (1<<4); // lba translation
- options |= (1<<5); // removable device
- options |= (1<<6); // atapi device
- options |= (mode==ATA_MODE_PIO32?1:0<<7);
-
- write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
- write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
- write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
- write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
- write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
- write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
- write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
- write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
-
- checksum=0;
- for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
- checksum = ~checksum;
- write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
- }
-
- // EDD 3.x
- if(size >= 0x42) {
- Bit8u channel, iface, checksum, i;
- Bit16u iobase1;
-
- channel = device / 2;
- iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
- iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
- write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
- write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
- write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
- write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
-
- if (iface==ATA_IFACE_ISA) {
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
- }
- else {
- // FIXME PCI
- }
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
-
- if (iface==ATA_IFACE_ISA) {
- write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
- write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
- write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
- }
- else {
- // FIXME PCI
- }
- write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
- write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
- write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
- write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
-
- checksum=0;
- for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
- checksum = ~checksum;
- write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
- }
-
- goto int13_success;
- break;
-
- case 0x49: // IBM/MS extended media change
- // always send changed ??
- SET_AH(06);
- goto int13_fail_nostatus;
- break;
-
- case 0x4e: // // IBM/MS set hardware configuration
- // DMA, prefetch, PIO maximum not supported
- switch (GET_AL()) {
- case 0x01:
- case 0x03:
- case 0x04:
- case 0x06:
- goto int13_success;
- break;
- default :
- goto int13_fail;
- }
- break;
-
- // all those functions return unimplemented
- case 0x02: /* read sectors */
- case 0x04: /* verify sectors */
- case 0x08: /* read disk drive parameters */
- case 0x0a: /* read disk sectors with ECC */
- case 0x0b: /* write disk sectors with ECC */
- case 0x18: /* set media type for format */
- case 0x50: // ? - send packet command
- default:
- BX_INFO("int13_cdrom: unsupported AH=%02x\n", GET_AH());
- goto int13_fail;
- break;
- }
-
-int13_fail:
- SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
-int13_fail_noah:
- SET_DISK_RET_STATUS(GET_AH());
-int13_fail_nostatus:
- SET_CF(); // error occurred
- return;
-
-int13_success:
- SET_AH(0x00); // no error
-int13_success_noah:
- SET_DISK_RET_STATUS(0x00);
- CLEAR_CF(); // no error
- return;
-}
-
-// ---------------------------------------------------------------------------
-// End of int13 for cdrom
-// ---------------------------------------------------------------------------
-
-#if BX_ELTORITO_BOOT
-// ---------------------------------------------------------------------------
-// Start of int13 for eltorito functions
-// ---------------------------------------------------------------------------
-
- void
-int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
-
- BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
- // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI);
-
- switch (GET_AH()) {
-
- // FIXME ElTorito Various. Should be implemented
- case 0x4a: // ElTorito - Initiate disk emu
- case 0x4c: // ElTorito - Initiate disk emu and boot
- case 0x4d: // ElTorito - Return Boot catalog
- BX_PANIC("Int13 eltorito call with AX=%04x. Please report\n",AX);
- goto int13_fail;
- break;
-
- case 0x4b: // ElTorito - Terminate disk emu
- // FIXME ElTorito Hardcoded
- write_byte(DS,SI+0x00,0x13);
- write_byte(DS,SI+0x01,read_byte(ebda_seg,&EbdaData->cdemu.media));
- write_byte(DS,SI+0x02,read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive));
- write_byte(DS,SI+0x03,read_byte(ebda_seg,&EbdaData->cdemu.controller_index));
- write_dword(DS,SI+0x04,read_dword(ebda_seg,&EbdaData->cdemu.ilba));
- write_word(DS,SI+0x08,read_word(ebda_seg,&EbdaData->cdemu.device_spec));
- write_word(DS,SI+0x0a,read_word(ebda_seg,&EbdaData->cdemu.buffer_segment));
- write_word(DS,SI+0x0c,read_word(ebda_seg,&EbdaData->cdemu.load_segment));
- write_word(DS,SI+0x0e,read_word(ebda_seg,&EbdaData->cdemu.sector_count));
- write_byte(DS,SI+0x10,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.cylinders));
- write_byte(DS,SI+0x11,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.spt));
- write_byte(DS,SI+0x12,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.heads));
-
- // If we have to terminate emulation
- if(GET_AL() == 0x00) {
- // FIXME ElTorito Various. Should be handled accordingly to spec
- write_byte(ebda_seg,&EbdaData->cdemu.active, 0x00); // bye bye
- }
-
- goto int13_success;
- break;
-
- default:
- BX_INFO("int13_eltorito: unsupported AH=%02x\n", GET_AH());
- goto int13_fail;
- break;
- }
-
-int13_fail:
- SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
- SET_DISK_RET_STATUS(GET_AH());
- SET_CF(); // error occurred
- return;
-
-int13_success:
- SET_AH(0x00); // no error
- SET_DISK_RET_STATUS(0x00);
- CLEAR_CF(); // no error
- return;
-}
-
-// ---------------------------------------------------------------------------
-// End of int13 for eltorito functions
-// ---------------------------------------------------------------------------
-
-// ---------------------------------------------------------------------------
-// Start of int13 when emulating a device from the cd
-// ---------------------------------------------------------------------------
-
- void
-int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u device, status;
- Bit16u vheads, vspt, vcylinders;
- Bit16u head, sector, cylinder, nbsectors;
- Bit32u vlba, ilba, slba, elba;
- Bit16u before, segment, offset;
- Bit8u atacmd[12];
-
- BX_DEBUG_INT13_ET("int13_cdemu: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
-
- /* at this point, we are emulating a floppy/harddisk */
-
- // Recompute the device number
- device = read_byte(ebda_seg,&EbdaData->cdemu.controller_index) * 2;
- device += read_byte(ebda_seg,&EbdaData->cdemu.device_spec);
-
- SET_DISK_RET_STATUS(0x00);
-
- /* basic checks : emulation should be active, dl should equal the emulated drive */
- if( (read_byte(ebda_seg,&EbdaData->cdemu.active) ==0 )
- || (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive ) != GET_DL())) {
- BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", GET_AH(), GET_DL());
- goto int13_fail;
- }
-
- switch (GET_AH()) {
-
- // all those functions return SUCCESS
- case 0x00: /* disk controller reset */
- case 0x09: /* initialize drive parameters */
- case 0x0c: /* seek to specified cylinder */
- case 0x0d: /* alternate disk reset */ // FIXME ElTorito Various. should really reset ?
- case 0x10: /* check drive ready */ // FIXME ElTorito Various. should check if ready ?
- case 0x11: /* recalibrate */
- case 0x14: /* controller internal diagnostic */
- case 0x16: /* detect disk change */
- goto int13_success;
- break;
-
- // all those functions return disk write-protected
- case 0x03: /* write disk sectors */
- case 0x05: /* format disk track */
- SET_AH(0x03);
- goto int13_fail_noah;
- break;
-
- case 0x01: /* read disk status */
- status=read_byte(0x0040, 0x0074);
- SET_AH(status);
- SET_DISK_RET_STATUS(0);
-
- /* set CF if error status read */
- if (status) goto int13_fail_nostatus;
- else goto int13_success_noah;
- break;
-
- case 0x02: // read disk sectors
- case 0x04: // verify disk sectors
- vspt = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt);
- vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders);
- vheads = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads);
-
- ilba = read_dword(ebda_seg,&EbdaData->cdemu.ilba);
-
- sector = GET_CL() & 0x003f;
- cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH();
- head = GET_DH();
- nbsectors = GET_AL();
- segment = ES;
- offset = BX;
-
- // no sector to read ?
- if(nbsectors==0) goto int13_success;
-
- // sanity checks sco openserver needs this!
- if ((sector > vspt)
- || (cylinder >= vcylinders)
- || (head >= vheads)) {
- goto int13_fail;
- }
-
- // After controls, verify do nothing
- if (GET_AH() == 0x04) goto int13_success;
-
- segment = ES+(BX / 16);
- offset = BX % 16;
-
- // calculate the virtual lba inside the image
- vlba=((((Bit32u)cylinder*(Bit32u)vheads)+(Bit32u)head)*(Bit32u)vspt)+((Bit32u)(sector-1));
-
- // In advance so we don't loose the count
- SET_AL(nbsectors);
-
- // start lba on cd
- slba = (Bit32u)vlba/4;
- before= (Bit16u)vlba%4;
-
- // end lba on cd
- elba = (Bit32u)(vlba+nbsectors-1)/4;
-
- memsetb(get_SS(),atacmd,0,12);
- atacmd[0]=0x28; // READ command
- atacmd[7]=((Bit16u)(elba-slba+1) & 0xff00) >> 8; // Sectors
- atacmd[8]=((Bit16u)(elba-slba+1) & 0x00ff); // Sectors
- atacmd[2]=(ilba+slba & 0xff000000) >> 24; // LBA
- atacmd[3]=(ilba+slba & 0x00ff0000) >> 16;
- atacmd[4]=(ilba+slba & 0x0000ff00) >> 8;
- atacmd[5]=(ilba+slba & 0x000000ff);
- if((status = ata_cmd_packet(device, 12, get_SS(), atacmd, before*512, nbsectors*512L, ATA_DATA_IN, segment,offset)) != 0) {
- BX_INFO("int13_cdemu: function %02x, error %02x !\n",GET_AH(),status);
- SET_AH(0x02);
- SET_AL(0);
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x08: /* read disk drive parameters */
- vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt);
- vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1;
- vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1;
-
- SET_AL( 0x00 );
- SET_BL( 0x00 );
- SET_CH( vcylinders & 0xff );
- SET_CL((( vcylinders >> 2) & 0xc0) | ( vspt & 0x3f ));
- SET_DH( vheads );
- SET_DL( 0x02 ); // FIXME ElTorito Various. should send the real count of drives 1 or 2
- // FIXME ElTorito Harddisk. should send the HD count
-
- switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
- case 0x01: SET_BL( 0x02 ); break;
- case 0x02: SET_BL( 0x04 ); break;
- case 0x03: SET_BL( 0x06 ); break;
- }
-
-ASM_START
- push bp
- mov bp, sp
- mov ax, #diskette_param_table2
- mov _int13_cdemu.DI+2[bp], ax
- mov _int13_cdemu.ES+2[bp], cs
- pop bp
-ASM_END
- goto int13_success;
- break;
-
- case 0x15: /* read disk drive size */
- // FIXME ElTorito Harddisk. What geometry to send ?
- SET_AH(0x03);
- goto int13_success_noah;
- break;
-
- // all those functions return unimplemented
- case 0x0a: /* read disk sectors with ECC */
- case 0x0b: /* write disk sectors with ECC */
- case 0x18: /* set media type for format */
- case 0x41: // IBM/MS installation check
- // FIXME ElTorito Harddisk. Darwin would like to use EDD
- case 0x42: // IBM/MS extended read
- case 0x43: // IBM/MS extended write
- case 0x44: // IBM/MS verify sectors
- case 0x45: // IBM/MS lock/unlock drive
- case 0x46: // IBM/MS eject media
- case 0x47: // IBM/MS extended seek
- case 0x48: // IBM/MS get drive parameters
- case 0x49: // IBM/MS extended media change
- case 0x4e: // ? - set hardware configuration
- case 0x50: // ? - send packet command
- default:
- BX_INFO("int13_cdemu function AH=%02x unsupported, returns fail\n", GET_AH());
- goto int13_fail;
- break;
- }
-
-int13_fail:
- SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
-int13_fail_noah:
- SET_DISK_RET_STATUS(GET_AH());
-int13_fail_nostatus:
- SET_CF(); // error occurred
- return;
-
-int13_success:
- SET_AH(0x00); // no error
-int13_success_noah:
- SET_DISK_RET_STATUS(0x00);
- CLEAR_CF(); // no error
- return;
-}
-
-// ---------------------------------------------------------------------------
-// End of int13 when emulating a device from the cd
-// ---------------------------------------------------------------------------
-
-#endif // BX_ELTORITO_BOOT
-
-#else //BX_USE_ATADRV
-
- void
-outLBA(cylinder,hd_heads,head,hd_sectors,sector,dl)
- Bit16u cylinder;
- Bit16u hd_heads;
- Bit16u head;
- Bit16u hd_sectors;
- Bit16u sector;
- Bit16u dl;
-{
-ASM_START
- push bp
- mov bp, sp
- push eax
- push ebx
- push edx
- xor eax,eax
- mov ax,4[bp] // cylinder
- xor ebx,ebx
- mov bl,6[bp] // hd_heads
- imul ebx
-
- mov bl,8[bp] // head
- add eax,ebx
- mov bl,10[bp] // hd_sectors
- imul ebx
- mov bl,12[bp] // sector
- add eax,ebx
-
- dec eax
- mov dx,#0x1f3
- out dx,al
- mov dx,#0x1f4
- mov al,ah
- out dx,al
- shr eax,#16
- mov dx,#0x1f5
- out dx,al
- and ah,#0xf
- mov bl,14[bp] // dl
- and bl,#1
- shl bl,#4
- or ah,bl
- or ah,#0xe0
- mov al,ah
- mov dx,#0x01f6
- out dx,al
- pop edx
- pop ebx
- pop eax
- pop bp
-ASM_END
-}
-
- void
-int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit8u drive, num_sectors, sector, head, status, mod;
- Bit8u drive_map;
- Bit8u n_drives;
- Bit16u cyl_mod, ax;
- Bit16u max_cylinder, cylinder, total_sectors;
- Bit16u hd_cylinders;
- Bit8u hd_heads, hd_sectors;
- Bit16u val16;
- Bit8u sector_count;
- unsigned int i;
- Bit16u tempbx;
- Bit16u dpsize;
-
- Bit16u count, segment, offset;
- Bit32u lba;
- Bit16u error;
-
- BX_DEBUG_INT13_HD("int13 harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
-
- write_byte(0x0040, 0x008e, 0); // clear completion flag
-
- /* at this point, DL is >= 0x80 to be passed from the floppy int13h
- handler code */
- /* check how many disks first (cmos reg 0x12), return an error if
- drive not present */
- drive_map = inb_cmos(0x12);
- drive_map = (((drive_map & 0xf0)==0) ? 0 : 1) |
- (((drive_map & 0x0f)==0) ? 0 : 2);
- n_drives = (drive_map==0) ? 0 :
- ((drive_map==3) ? 2 : 1);
-
- if (!(drive_map & (1<<(GET_ELDL()&0x7f)))) { /* allow 0, 1, or 2 disks */
- SET_AH(0x01);
- SET_DISK_RET_STATUS(0x01);
- SET_CF(); /* error occurred */
- return;
- }
-
- switch (GET_AH()) {
-
- case 0x00: /* disk controller reset */
-BX_DEBUG_INT13_HD("int13_f00\n");
-
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- set_diskette_ret_status(0);
- set_diskette_current_cyl(0, 0); /* current cylinder, diskette 1 */
- set_diskette_current_cyl(1, 0); /* current cylinder, diskette 2 */
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x01: /* read disk status */
-BX_DEBUG_INT13_HD("int13_f01\n");
- status = read_byte(0x0040, 0x0074);
- SET_AH(status);
- SET_DISK_RET_STATUS(0);
- /* set CF if error status read */
- if (status) SET_CF();
- else CLEAR_CF();
- return;
- break;
-
- case 0x04: // verify disk sectors
- case 0x02: // read disk sectors
- drive = GET_ELDL();
- get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
-
- num_sectors = GET_AL();
- cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH();
- sector = (GET_CL() & 0x3f);
- head = GET_DH();
-
-
- if (hd_cylinders > 1024) {
- if (hd_cylinders <= 2048) {
- cylinder <<= 1;
- }
- else if (hd_cylinders <= 4096) {
- cylinder <<= 2;
- }
- else if (hd_cylinders <= 8192) {
- cylinder <<= 3;
- }
- else { // hd_cylinders <= 16384
- cylinder <<= 4;
- }
-
- ax = head / hd_heads;
- cyl_mod = ax & 0xff;
- head = ax >> 8;
- cylinder |= cyl_mod;
- }
-
- if ( (cylinder >= hd_cylinders) ||
- (sector > hd_sectors) ||
- (head >= hd_heads) ) {
- SET_AH(1);
- SET_DISK_RET_STATUS(1);
- SET_CF(); /* error occurred */
- return;
- }
-
- if ( (num_sectors > 128) || (num_sectors == 0) )
- BX_PANIC("int13_harddisk: num_sectors out of range!\n");
-
- if (head > 15)
- BX_PANIC("hard drive BIOS:(read/verify) head > 15\n");
-
- if ( GET_AH() == 0x04 ) {
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF();
- return;
- }
-
- status = inb(0x1f7);
- if (status & 0x80) {
- BX_PANIC("hard drive BIOS:(read/verify) BUSY bit set\n");
- }
- outb(0x01f2, num_sectors);
- /* activate LBA? (tomv) */
- if (hd_heads > 16) {
-BX_DEBUG_INT13_HD("CHS: %x %x %x\n", cylinder, head, sector);
- outLBA(cylinder,hd_heads,head,hd_sectors,sector,drive);
- }
- else {
- outb(0x01f3, sector);
- outb(0x01f4, cylinder & 0x00ff);
- outb(0x01f5, cylinder >> 8);
- outb(0x01f6, 0xa0 | ((drive & 0x01)<<4) | (head & 0x0f));
- }
- outb(0x01f7, 0x20);
-
- while (1) {
- status = inb(0x1f7);
- if ( !(status & 0x80) ) break;
- }
-
- if (status & 0x01) {
- BX_PANIC("hard drive BIOS:(read/verify) read error\n");
- } else if ( !(status & 0x08) ) {
- BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status);
- BX_PANIC("hard drive BIOS:(read/verify) expected DRQ=1\n");
- }
-
- sector_count = 0;
- tempbx = BX;
-
-ASM_START
- sti ;; enable higher priority interrupts
-ASM_END
-
- while (1) {
-ASM_START
- ;; store temp bx in real DI register
- push bp
- mov bp, sp
- mov di, _int13_harddisk.tempbx + 2 [bp]
- pop bp
-
- ;; adjust if there will be an overrun
- cmp di, #0xfe00
- jbe i13_f02_no_adjust
-i13_f02_adjust:
- sub di, #0x0200 ; sub 512 bytes from offset
- mov ax, es
- add ax, #0x0020 ; add 512 to segment
- mov es, ax
-
-i13_f02_no_adjust:
- mov cx, #0x0100 ;; counter (256 words = 512b)
- mov dx, #0x01f0 ;; AT data read port
-
- rep
- insw ;; CX words transfered from port(DX) to ES:[DI]
-
-i13_f02_done:
- ;; store real DI register back to temp bx
- push bp
- mov bp, sp
- mov _int13_harddisk.tempbx + 2 [bp], di
- pop bp
-ASM_END
-
- sector_count++;
- num_sectors--;
- if (num_sectors == 0) {
- status = inb(0x1f7);
- if ( (status & 0xc9) != 0x40 )
- BX_PANIC("no sectors left to read/verify, status is %02x\n", (unsigned) status);
- break;
- }
- else {
- status = inb(0x1f7);
- if ( (status & 0xc9) != 0x48 )
- BX_PANIC("more sectors left to read/verify, status is %02x\n", (unsigned) status);
- continue;
- }
- }
-
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- SET_AL(sector_count);
- CLEAR_CF(); /* successful */
- return;
- break;
-
-
- case 0x03: /* write disk sectors */
-BX_DEBUG_INT13_HD("int13_f03\n");
- drive = GET_ELDL ();
- get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
-
- num_sectors = GET_AL();
- cylinder = GET_CH();
- cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300;
- sector = (GET_CL() & 0x3f);
- head = GET_DH();
-
- if (hd_cylinders > 1024) {
- if (hd_cylinders <= 2048) {
- cylinder <<= 1;
- }
- else if (hd_cylinders <= 4096) {
- cylinder <<= 2;
- }
- else if (hd_cylinders <= 8192) {
- cylinder <<= 3;
- }
- else { // hd_cylinders <= 16384
- cylinder <<= 4;
- }
-
- ax = head / hd_heads;
- cyl_mod = ax & 0xff;
- head = ax >> 8;
- cylinder |= cyl_mod;
- }
-
- if ( (cylinder >= hd_cylinders) ||
- (sector > hd_sectors) ||
- (head >= hd_heads) ) {
- SET_AH( 1);
- SET_DISK_RET_STATUS(1);
- SET_CF(); /* error occurred */
- return;
- }
-
- if ( (num_sectors > 128) || (num_sectors == 0) )
- BX_PANIC("int13_harddisk: num_sectors out of range!\n");
-
- if (head > 15)
- BX_PANIC("hard drive BIOS:(read) head > 15\n");
-
- status = inb(0x1f7);
- if (status & 0x80) {
- BX_PANIC("hard drive BIOS:(read) BUSY bit set\n");
- }
-// should check for Drive Ready Bit also in status reg
- outb(0x01f2, num_sectors);
-
- /* activate LBA? (tomv) */
- if (hd_heads > 16) {
-BX_DEBUG_INT13_HD("CHS (write): %x %x %x\n", cylinder, head, sector);
- outLBA(cylinder,hd_heads,head,hd_sectors,sector,GET_ELDL());
- }
- else {
- outb(0x01f3, sector);
- outb(0x01f4, cylinder & 0x00ff);
- outb(0x01f5, cylinder >> 8);
- outb(0x01f6, 0xa0 | ((GET_ELDL() & 0x01)<<4) | (head & 0x0f));
- }
- outb(0x01f7, 0x30);
-
- // wait for busy bit to turn off after seeking
- while (1) {
- status = inb(0x1f7);
- if ( !(status & 0x80) ) break;
- }
-
- if ( !(status & 0x08) ) {
- BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status);
- BX_PANIC("hard drive BIOS:(write) data-request bit not set\n");
- }
-
- sector_count = 0;
- tempbx = BX;
-
-ASM_START
- sti ;; enable higher priority interrupts
-ASM_END
-
- while (1) {
-ASM_START
- ;; store temp bx in real SI register
- push bp
- mov bp, sp
- mov si, _int13_harddisk.tempbx + 2 [bp]
- pop bp
-
- ;; adjust if there will be an overrun
- cmp si, #0xfe00
- jbe i13_f03_no_adjust
-i13_f03_adjust:
- sub si, #0x0200 ; sub 512 bytes from offset
- mov ax, es
- add ax, #0x0020 ; add 512 to segment
- mov es, ax
-
-i13_f03_no_adjust:
- mov cx, #0x0100 ;; counter (256 words = 512b)
- mov dx, #0x01f0 ;; AT data read port
-
- seg ES
- rep
- outsw ;; CX words tranfered from ES:[SI] to port(DX)
-
- ;; store real SI register back to temp bx
- push bp
- mov bp, sp
- mov _int13_harddisk.tempbx + 2 [bp], si
- pop bp
-ASM_END
-
- sector_count++;
- num_sectors--;
- if (num_sectors == 0) {
- status = inb(0x1f7);
- if ( (status & 0xe9) != 0x40 )
- BX_PANIC("no sectors left to write, status is %02x\n", (unsigned) status);
- break;
- }
- else {
- status = inb(0x1f7);
- if ( (status & 0xc9) != 0x48 )
- BX_PANIC("more sectors left to write, status is %02x\n", (unsigned) status);
- continue;
- }
- }
-
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- SET_AL(sector_count);
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x05: /* format disk track */
-BX_DEBUG_INT13_HD("int13_f05\n");
- BX_PANIC("format disk track called\n");
- /* nop */
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x08: /* read disk drive parameters */
-BX_DEBUG_INT13_HD("int13_f08\n");
-
- drive = GET_ELDL ();
- get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
-
- // translate CHS
- //
- if (hd_cylinders <= 1024) {
- // hd_cylinders >>= 0;
- // hd_heads <<= 0;
- }
- else if (hd_cylinders <= 2048) {
- hd_cylinders >>= 1;
- hd_heads <<= 1;
- }
- else if (hd_cylinders <= 4096) {
- hd_cylinders >>= 2;
- hd_heads <<= 2;
- }
- else if (hd_cylinders <= 8192) {
- hd_cylinders >>= 3;
- hd_heads <<= 3;
- }
- else { // hd_cylinders <= 16384
- hd_cylinders >>= 4;
- hd_heads <<= 4;
- }
-
- max_cylinder = hd_cylinders - 2; /* 0 based */
- SET_AL(0);
- SET_CH(max_cylinder & 0xff);
- SET_CL(((max_cylinder >> 2) & 0xc0) | (hd_sectors & 0x3f));
- SET_DH(hd_heads - 1);
- SET_DL(n_drives); /* returns 0, 1, or 2 hard drives */
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
-
- return;
- break;
-
- case 0x09: /* initialize drive parameters */
-BX_DEBUG_INT13_HD("int13_f09\n");
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x0a: /* read disk sectors with ECC */
-BX_DEBUG_INT13_HD("int13_f0a\n");
- case 0x0b: /* write disk sectors with ECC */
-BX_DEBUG_INT13_HD("int13_f0b\n");
- BX_PANIC("int13h Functions 0Ah & 0Bh not implemented!\n");
- return;
- break;
-
- case 0x0c: /* seek to specified cylinder */
-BX_DEBUG_INT13_HD("int13_f0c\n");
- BX_INFO("int13h function 0ch (seek) not implemented!\n");
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x0d: /* alternate disk reset */
-BX_DEBUG_INT13_HD("int13_f0d\n");
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x10: /* check drive ready */
-BX_DEBUG_INT13_HD("int13_f10\n");
- //SET_AH(0);
- //SET_DISK_RET_STATUS(0);
- //CLEAR_CF(); /* successful */
- //return;
- //break;
-
- // should look at 40:8E also???
- status = inb(0x01f7);
- if ( (status & 0xc0) == 0x40 ) {
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); // drive ready
- return;
- }
- else {
- SET_AH(0xAA);
- SET_DISK_RET_STATUS(0xAA);
- SET_CF(); // not ready
- return;
- }
- break;
-
- case 0x11: /* recalibrate */
-BX_DEBUG_INT13_HD("int13_f11\n");
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
- return;
- break;
-
- case 0x14: /* controller internal diagnostic */
-BX_DEBUG_INT13_HD("int13_f14\n");
- SET_AH(0);
- SET_DISK_RET_STATUS(0);
- CLEAR_CF(); /* successful */
- SET_AL(0);
- return;
- break;
-
- case 0x15: /* read disk drive size */
- drive = GET_ELDL();
- get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
-ASM_START
- push bp
- mov bp, sp
- mov al, _int13_harddisk.hd_heads + 2 [bp]
- mov ah, _int13_harddisk.hd_sectors + 2 [bp]
- mul al, ah ;; ax = heads * sectors
- mov bx, _int13_harddisk.hd_cylinders + 2 [bp]
- dec bx ;; use (cylinders - 1) ???
- mul ax, bx ;; dx:ax = (cylinders -1) * (heads * sectors)
- ;; now we need to move the 32bit result dx:ax to what the
- ;; BIOS wants which is cx:dx.
- ;; and then into CX:DX on the stack
- mov _int13_harddisk.CX + 2 [bp], dx
- mov _int13_harddisk.DX + 2 [bp], ax
- pop bp
-ASM_END
- SET_AH(3); // hard disk accessible
- SET_DISK_RET_STATUS(0); // ??? should this be 0
- CLEAR_CF(); // successful
- return;
- break;
-
- case 0x18: // set media type for format
- case 0x41: // IBM/MS
- case 0x42: // IBM/MS
- case 0x43: // IBM/MS
- case 0x44: // IBM/MS
- case 0x45: // IBM/MS lock/unlock drive
- case 0x46: // IBM/MS eject media
- case 0x47: // IBM/MS extended seek
- case 0x49: // IBM/MS extended media change
- case 0x50: // IBM/MS send packet command
- default:
- BX_INFO("int13_harddisk: unsupported AH=%02x\n", GET_AH());
-
- SET_AH(1); // code=invalid function in AH or invalid parameter
- SET_DISK_RET_STATUS(1);
- SET_CF(); /* unsuccessful */
- return;
- break;
- }
-}
-
-static char panic_msg_reg12h[] = "HD%d cmos reg 12h not type F\n";
-static char panic_msg_reg19h[] = "HD%d cmos reg %02xh not user definable type 47\n";
-
- void
-get_hd_geometry(drive, hd_cylinders, hd_heads, hd_sectors)
- Bit8u drive;
- Bit16u *hd_cylinders;
- Bit8u *hd_heads;
- Bit8u *hd_sectors;
-{
- Bit8u hd_type;
- Bit16u ss;
- Bit16u cylinders;
- Bit8u iobase;
-
- ss = get_SS();
- if (drive == 0x80) {
- hd_type = inb_cmos(0x12) & 0xf0;
- if (hd_type != 0xf0)
- BX_INFO(panic_msg_reg12h,0);
- hd_type = inb_cmos(0x19); // HD0: extended type
- if (hd_type != 47)
- BX_INFO(panic_msg_reg19h,0,0x19);
- iobase = 0x1b;
- } else {
- hd_type = inb_cmos(0x12) & 0x0f;
- if (hd_type != 0x0f)
- BX_INFO(panic_msg_reg12h,1);
- hd_type = inb_cmos(0x1a); // HD1: extended type
- if (hd_type != 47)
- BX_INFO(panic_msg_reg19h,0,0x1a);
- iobase = 0x24;
- }
-
- // cylinders
- cylinders = inb_cmos(iobase) | (inb_cmos(iobase+1) << 8);
- write_word(ss, hd_cylinders, cylinders);
-
- // heads
- write_byte(ss, hd_heads, inb_cmos(iobase+2));
-
- // sectors per track
- write_byte(ss, hd_sectors, inb_cmos(iobase+8));
-}
-
-#endif //else BX_USE_ATADRV
-
-#if BX_SUPPORT_FLOPPY
-
-//////////////////////
-// FLOPPY functions //
-//////////////////////
-
-void floppy_reset_controller()
-{
- Bit8u val8;
-
- // Reset controller
- val8 = inb(0x03f2);
- outb(0x03f2, val8 & ~0x04);
- outb(0x03f2, val8 | 0x04);
-
- // Wait for controller to come out of reset
- do {
- val8 = inb(0x3f4);
- } while ( (val8 & 0xc0) != 0x80 );
-}
-
-void floppy_prepare_controller(drive)
- Bit16u drive;
-{
- Bit8u val8, dor, prev_reset;
-
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0040, 0x003e);
- val8 &= 0x7f;
- write_byte(0x0040, 0x003e, val8);
-
- // turn on motor of selected drive, DMA & int enabled, normal operation
- prev_reset = inb(0x03f2) & 0x04;
- if (drive)
- dor = 0x20;
- else
- dor = 0x10;
- dor |= 0x0c;
- dor |= drive;
- outb(0x03f2, dor);
-
- // reset the disk motor timeout value of INT 08
- write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
-
- // wait for drive readiness
- do {
- val8 = inb(0x3f4);
- } while ( (val8 & 0xc0) != 0x80 );
-
- if (prev_reset == 0) {
- // turn on interrupts
-ASM_START
- sti
-ASM_END
- // wait on 40:3e bit 7 to become 1
- do {
- val8 = read_byte(0x0040, 0x003e);
- } while ( (val8 & 0x80) == 0 );
- val8 &= 0x7f;
-ASM_START
- cli
-ASM_END
- write_byte(0x0040, 0x003e, val8);
- }
-}
-
- bx_bool
-floppy_media_known(drive)
- Bit16u drive;
-{
- Bit8u val8;
- Bit16u media_state_offset;
-
- val8 = read_byte(0x0040, 0x003e); // diskette recal status
- if (drive)
- val8 >>= 1;
- val8 &= 0x01;
- if (val8 == 0)
- return(0);
-
- media_state_offset = 0x0090;
- if (drive)
- media_state_offset += 1;
-
- val8 = read_byte(0x0040, media_state_offset);
- val8 = (val8 >> 4) & 0x01;
- if (val8 == 0)
- return(0);
-
- // check pass, return KNOWN
- return(1);
-}
-
- bx_bool
-floppy_media_sense(drive)
- Bit16u drive;
-{
- bx_bool retval;
- Bit16u media_state_offset;
- Bit8u drive_type, config_data, media_state;
-
- if (floppy_drive_recal(drive) == 0) {
- return(0);
- }
-
- // for now cheat and get drive type from CMOS,
- // assume media is same as drive type
-
- // ** config_data **
- // Bitfields for diskette media control:
- // Bit(s) Description (Table M0028)
- // 7-6 last data rate set by controller
- // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
- // 5-4 last diskette drive step rate selected
- // 00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah
- // 3-2 {data rate at start of operation}
- // 1-0 reserved
-
- // ** media_state **
- // Bitfields for diskette drive media state:
- // Bit(s) Description (Table M0030)
- // 7-6 data rate
- // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
- // 5 double stepping required (e.g. 360kB in 1.2MB)
- // 4 media type established
- // 3 drive capable of supporting 4MB media
- // 2-0 on exit from BIOS, contains
- // 000 trying 360kB in 360kB
- // 001 trying 360kB in 1.2MB
- // 010 trying 1.2MB in 1.2MB
- // 011 360kB in 360kB established
- // 100 360kB in 1.2MB established
- // 101 1.2MB in 1.2MB established
- // 110 reserved
- // 111 all other formats/drives
-
- drive_type = inb_cmos(0x10);
- if (drive == 0)
- drive_type >>= 4;
- else
- drive_type &= 0x0f;
- if ( drive_type == 1 ) {
- // 360K 5.25" drive
- config_data = 0x00; // 0000 0000
- media_state = 0x25; // 0010 0101
- retval = 1;
- }
- else if ( drive_type == 2 ) {
- // 1.2 MB 5.25" drive
- config_data = 0x00; // 0000 0000
- media_state = 0x25; // 0010 0101 // need double stepping??? (bit 5)
- retval = 1;
- }
- else if ( drive_type == 3 ) {
- // 720K 3.5" drive
- config_data = 0x00; // 0000 0000 ???
- media_state = 0x17; // 0001 0111
- retval = 1;
- }
- else if ( drive_type == 4 ) {
- // 1.44 MB 3.5" drive
- config_data = 0x00; // 0000 0000
- media_state = 0x17; // 0001 0111
- retval = 1;
- }
- else if ( drive_type == 5 ) {
- // 2.88 MB 3.5" drive
- config_data = 0xCC; // 1100 1100
- media_state = 0xD7; // 1101 0111
- retval = 1;
- }
- //
- // Extended floppy size uses special cmos setting
- else if ( drive_type == 6 ) {
- // 160k 5.25" drive
- config_data = 0x00; // 0000 0000
- media_state = 0x27; // 0010 0111
- retval = 1;
- }
- else if ( drive_type == 7 ) {
- // 180k 5.25" drive
- config_data = 0x00; // 0000 0000
- media_state = 0x27; // 0010 0111
- retval = 1;
- }
- else if ( drive_type == 8 ) {
- // 320k 5.25" drive
- config_data = 0x00; // 0000 0000
- media_state = 0x27; // 0010 0111
- retval = 1;
- }
-
- else {
- // not recognized
- config_data = 0x00; // 0000 0000
- media_state = 0x00; // 0000 0000
- retval = 0;
- }
-
- if (drive == 0)
- media_state_offset = 0x90;
- else
- media_state_offset = 0x91;
- write_byte(0x0040, 0x008B, config_data);
- write_byte(0x0040, media_state_offset, media_state);
-
- return(retval);
-}
-
- bx_bool
-floppy_drive_recal(drive)
- Bit16u drive;
-{
- Bit8u val8;
- Bit16u curr_cyl_offset;
-
- floppy_prepare_controller(drive);
-
- // send Recalibrate command (2 bytes) to controller
- outb(0x03f5, 0x07); // 07: Recalibrate
- outb(0x03f5, drive); // 0=drive0, 1=drive1
-
- // turn on interrupts
-ASM_START
- sti
-ASM_END
-
- // wait on 40:3e bit 7 to become 1
- do {
- val8 = (read_byte(0x0040, 0x003e) & 0x80);
- } while ( val8 == 0 );
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
-ASM_START
- cli
-ASM_END
-
- // set 40:3e bit 7 to 0, and calibrated bit
- val8 = read_byte(0x0040, 0x003e);
- val8 &= 0x7f;
- if (drive) {
- val8 |= 0x02; // Drive 1 calibrated
- curr_cyl_offset = 0x0095;
- } else {
- val8 |= 0x01; // Drive 0 calibrated
- curr_cyl_offset = 0x0094;
- }
- write_byte(0x0040, 0x003e, val8);
- write_byte(0x0040, curr_cyl_offset, 0); // current cylinder is 0
-
- return(1);
-}
-
-
-
- bx_bool
-floppy_drive_exists(drive)
- Bit16u drive;
-{
- Bit8u drive_type;
-
- // check CMOS to see if drive exists
- drive_type = inb_cmos(0x10);
- if (drive == 0)
- drive_type >>= 4;
- else
- drive_type &= 0x0f;
- if ( drive_type == 0 )
- return(0);
- else
- return(1);
-}
-
- void
-int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit8u drive, num_sectors, track, sector, head, status;
- Bit16u base_address, base_count, base_es;
- Bit8u page, mode_register, val8, dor;
- Bit8u return_status[7];
- Bit8u drive_type, num_floppies, ah;
- Bit16u es, last_addr;
-
- BX_DEBUG_INT13_FL("int13_diskette: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
-
- ah = GET_AH();
-
- switch ( ah ) {
- case 0x00: // diskette controller reset
-BX_DEBUG_INT13_FL("floppy f00\n");
- drive = GET_ELDL();
- if (drive > 1) {
- SET_AH(1); // invalid param
- set_diskette_ret_status(1);
- SET_CF();
- return;
- }
- drive_type = inb_cmos(0x10);
-
- if (drive == 0)
- drive_type >>= 4;
- else
- drive_type &= 0x0f;
- if (drive_type == 0) {
- SET_AH(0x80); // drive not responding
- set_diskette_ret_status(0x80);
- SET_CF();
- return;
- }
- SET_AH(0);
- set_diskette_ret_status(0);
- CLEAR_CF(); // successful
- set_diskette_current_cyl(drive, 0); // current cylinder
- return;
-
- case 0x01: // Read Diskette Status
- CLEAR_CF();
- val8 = read_byte(0x0000, 0x0441);
- SET_AH(val8);
- if (val8) {
- SET_CF();
- }
- return;
-
- case 0x02: // Read Diskette Sectors
- case 0x03: // Write Diskette Sectors
- case 0x04: // Verify Diskette Sectors
- num_sectors = GET_AL();
- track = GET_CH();
- sector = GET_CL();
- head = GET_DH();
- drive = GET_ELDL();
-
- if ((drive > 1) || (head > 1) || (sector == 0) ||
- (num_sectors == 0) || (num_sectors > 72)) {
- BX_INFO("int13_diskette: read/write/verify: parameter out of range\n");
- SET_AH(1);
- set_diskette_ret_status(1);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
-
- // see if drive exists
- if (floppy_drive_exists(drive) == 0) {
- SET_AH(0x80); // not responding
- set_diskette_ret_status(0x80);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
-
- // see if media in drive, and type is known
- if (floppy_media_known(drive) == 0) {
- if (floppy_media_sense(drive) == 0) {
- SET_AH(0x0C); // Media type not found
- set_diskette_ret_status(0x0C);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
- }
-
- if (ah == 0x02) {
- // Read Diskette Sectors
-
- //-----------------------------------
- // set up DMA controller for transfer
- //-----------------------------------
-
- // es:bx = pointer to where to place information from diskette
- // port 04: DMA-1 base and current address, channel 2
- // port 05: DMA-1 base and current count, channel 2
- page = (ES >> 12); // upper 4 bits
- base_es = (ES << 4); // lower 16bits contributed by ES
- base_address = base_es + BX; // lower 16 bits of address
- // contributed by ES:BX
- if ( base_address < base_es ) {
- // in case of carry, adjust page by 1
- page++;
- }
- base_count = (num_sectors * 512) - 1;
-
- // check for 64K boundary overrun
- last_addr = base_address + base_count;
- if (last_addr < base_address) {
- SET_AH(0x09);
- set_diskette_ret_status(0x09);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
-
- BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
- outb(0x000a, 0x06);
-
- BX_DEBUG_INT13_FL("clear flip-flop\n");
- outb(0x000c, 0x00); // clear flip-flop
- outb(0x0004, base_address);
- outb(0x0004, base_address>>8);
- BX_DEBUG_INT13_FL("clear flip-flop\n");
- outb(0x000c, 0x00); // clear flip-flop
- outb(0x0005, base_count);
- outb(0x0005, base_count>>8);
-
- // port 0b: DMA-1 Mode Register
- mode_register = 0x46; // single mode, increment, autoinit disable,
- // transfer type=write, channel 2
- BX_DEBUG_INT13_FL("setting mode register\n");
- outb(0x000b, mode_register);
-
- BX_DEBUG_INT13_FL("setting page register\n");
- // port 81: DMA-1 Page Register, channel 2
- outb(0x0081, page);
-
- BX_DEBUG_INT13_FL("unmask chan 2\n");
- outb(0x000a, 0x02); // unmask channel 2
-
- BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n");
- outb(0x000a, 0x02);
-
- //--------------------------------------
- // set up floppy controller for transfer
- //--------------------------------------
- floppy_prepare_controller(drive);
-
- // send read-normal-data command (9 bytes) to controller
- outb(0x03f5, 0xe6); // e6: read normal data
- outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
- outb(0x03f5, track);
- outb(0x03f5, head);
- outb(0x03f5, sector);
- outb(0x03f5, 2); // 512 byte sector size
- outb(0x03f5, sector + num_sectors - 1); // last sector to read on track
- outb(0x03f5, 0); // Gap length
- outb(0x03f5, 0xff); // Gap length
-
- // turn on interrupts
- ASM_START
- sti
- ASM_END
-
- // wait on 40:3e bit 7 to become 1
- do {
- val8 = read_byte(0x0040, 0x0040);
- if (val8 == 0) {
- floppy_reset_controller();
- SET_AH(0x80); // drive not ready (timeout)
- set_diskette_ret_status(0x80);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
- val8 = (read_byte(0x0040, 0x003e) & 0x80);
- } while ( val8 == 0 );
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
- ASM_START
- cli
- ASM_END
-
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0040, 0x003e);
- val8 &= 0x7f;
- write_byte(0x0040, 0x003e, val8);
-
- // check port 3f4 for accessibility to status bytes
- val8 = inb(0x3f4);
- if ( (val8 & 0xc0) != 0xc0 )
- BX_PANIC("int13_diskette: ctrl not ready\n");
-
- // read 7 return status bytes from controller
- // using loop index broken, have to unroll...
- return_status[0] = inb(0x3f5);
- return_status[1] = inb(0x3f5);
- return_status[2] = inb(0x3f5);
- return_status[3] = inb(0x3f5);
- return_status[4] = inb(0x3f5);
- return_status[5] = inb(0x3f5);
- return_status[6] = inb(0x3f5);
- // record in BIOS Data Area
- write_byte(0x0040, 0x0042, return_status[0]);
- write_byte(0x0040, 0x0043, return_status[1]);
- write_byte(0x0040, 0x0044, return_status[2]);
- write_byte(0x0040, 0x0045, return_status[3]);
- write_byte(0x0040, 0x0046, return_status[4]);
- write_byte(0x0040, 0x0047, return_status[5]);
- write_byte(0x0040, 0x0048, return_status[6]);
-
- if ( (return_status[0] & 0xc0) != 0 ) {
- SET_AH(0x20);
- set_diskette_ret_status(0x20);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
-
- // ??? should track be new val from return_status[3] ?
- set_diskette_current_cyl(drive, track);
- // AL = number of sectors read (same value as passed)
- SET_AH(0x00); // success
- CLEAR_CF(); // success
- return;
- } else if (ah == 0x03) {
- // Write Diskette Sectors
-
- //-----------------------------------
- // set up DMA controller for transfer
- //-----------------------------------
-
- // es:bx = pointer to where to place information from diskette
- // port 04: DMA-1 base and current address, channel 2
- // port 05: DMA-1 base and current count, channel 2
- page = (ES >> 12); // upper 4 bits
- base_es = (ES << 4); // lower 16bits contributed by ES
- base_address = base_es + BX; // lower 16 bits of address
- // contributed by ES:BX
- if ( base_address < base_es ) {
- // in case of carry, adjust page by 1
- page++;
- }
- base_count = (num_sectors * 512) - 1;
-
- // check for 64K boundary overrun
- last_addr = base_address + base_count;
- if (last_addr < base_address) {
- SET_AH(0x09);
- set_diskette_ret_status(0x09);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
-
- BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
- outb(0x000a, 0x06);
-
- outb(0x000c, 0x00); // clear flip-flop
- outb(0x0004, base_address);
- outb(0x0004, base_address>>8);
- outb(0x000c, 0x00); // clear flip-flop
- outb(0x0005, base_count);
- outb(0x0005, base_count>>8);
-
- // port 0b: DMA-1 Mode Register
- mode_register = 0x4a; // single mode, increment, autoinit disable,
- // transfer type=read, channel 2
- outb(0x000b, mode_register);
-
- // port 81: DMA-1 Page Register, channel 2
- outb(0x0081, page);
-
- BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n");
- outb(0x000a, 0x02);
-
- //--------------------------------------
- // set up floppy controller for transfer
- //--------------------------------------
- floppy_prepare_controller(drive);
-
- // send write-normal-data command (9 bytes) to controller
- outb(0x03f5, 0xc5); // c5: write normal data
- outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
- outb(0x03f5, track);
- outb(0x03f5, head);
- outb(0x03f5, sector);
- outb(0x03f5, 2); // 512 byte sector size
- outb(0x03f5, sector + num_sectors - 1); // last sector to write on track
- outb(0x03f5, 0); // Gap length
- outb(0x03f5, 0xff); // Gap length
-
- // turn on interrupts
- ASM_START
- sti
- ASM_END
-
- // wait on 40:3e bit 7 to become 1
- do {
- val8 = read_byte(0x0040, 0x0040);
- if (val8 == 0) {
- floppy_reset_controller();
- SET_AH(0x80); // drive not ready (timeout)
- set_diskette_ret_status(0x80);
- SET_AL(0); // no sectors written
- SET_CF(); // error occurred
- return;
- }
- val8 = (read_byte(0x0040, 0x003e) & 0x80);
- } while ( val8 == 0 );
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
- ASM_START
- cli
- ASM_END
-
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0040, 0x003e);
- val8 &= 0x7f;
- write_byte(0x0040, 0x003e, val8);
-
- // check port 3f4 for accessibility to status bytes
- val8 = inb(0x3f4);
- if ( (val8 & 0xc0) != 0xc0 )
- BX_PANIC("int13_diskette: ctrl not ready\n");
-
- // read 7 return status bytes from controller
- // using loop index broken, have to unroll...
- return_status[0] = inb(0x3f5);
- return_status[1] = inb(0x3f5);
- return_status[2] = inb(0x3f5);
- return_status[3] = inb(0x3f5);
- return_status[4] = inb(0x3f5);
- return_status[5] = inb(0x3f5);
- return_status[6] = inb(0x3f5);
- // record in BIOS Data Area
- write_byte(0x0040, 0x0042, return_status[0]);
- write_byte(0x0040, 0x0043, return_status[1]);
- write_byte(0x0040, 0x0044, return_status[2]);
- write_byte(0x0040, 0x0045, return_status[3]);
- write_byte(0x0040, 0x0046, return_status[4]);
- write_byte(0x0040, 0x0047, return_status[5]);
- write_byte(0x0040, 0x0048, return_status[6]);
-
- if ( (return_status[0] & 0xc0) != 0 ) {
- if ( (return_status[1] & 0x02) != 0 ) {
- // diskette not writable.
- // AH=status code=0x03 (tried to write on write-protected disk)
- // AL=number of sectors written=0
- AX = 0x0300;
- SET_CF();
- return;
- } else {
- BX_PANIC("int13_diskette_function: read error\n");
- }
- }
-
- // ??? should track be new val from return_status[3] ?
- set_diskette_current_cyl(drive, track);
- // AL = number of sectors read (same value as passed)
- SET_AH(0x00); // success
- CLEAR_CF(); // success
- return;
- } else { // if (ah == 0x04)
- // Verify Diskette Sectors
-
- // ??? should track be new val from return_status[3] ?
- set_diskette_current_cyl(drive, track);
- // AL = number of sectors verified (same value as passed)
- CLEAR_CF(); // success
- SET_AH(0x00); // success
- return;
- }
- break;
-
- case 0x05: // format diskette track
-BX_DEBUG_INT13_FL("floppy f05\n");
-
- num_sectors = GET_AL();
- track = GET_CH();
- head = GET_DH();
- drive = GET_ELDL();
-
- if ((drive > 1) || (head > 1) || (track > 79) ||
- (num_sectors == 0) || (num_sectors > 18)) {
- SET_AH(1);
- set_diskette_ret_status(1);
- SET_CF(); // error occurred
- }
-
- // see if drive exists
- if (floppy_drive_exists(drive) == 0) {
- SET_AH(0x80); // drive not responding
- set_diskette_ret_status(0x80);
- SET_CF(); // error occurred
- return;
- }
-
- // see if media in drive, and type is known
- if (floppy_media_known(drive) == 0) {
- if (floppy_media_sense(drive) == 0) {
- SET_AH(0x0C); // Media type not found
- set_diskette_ret_status(0x0C);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
- }
-
- // set up DMA controller for transfer
- page = (ES >> 12); // upper 4 bits
- base_es = (ES << 4); // lower 16bits contributed by ES
- base_address = base_es + BX; // lower 16 bits of address
- // contributed by ES:BX
- if ( base_address < base_es ) {
- // in case of carry, adjust page by 1
- page++;
- }
- base_count = (num_sectors * 4) - 1;
-
- // check for 64K boundary overrun
- last_addr = base_address + base_count;
- if (last_addr < base_address) {
- SET_AH(0x09);
- set_diskette_ret_status(0x09);
- SET_AL(0); // no sectors read
- SET_CF(); // error occurred
- return;
- }
-
- outb(0x000a, 0x06);
- outb(0x000c, 0x00); // clear flip-flop
- outb(0x0004, base_address);
- outb(0x0004, base_address>>8);
- outb(0x000c, 0x00); // clear flip-flop
- outb(0x0005, base_count);
- outb(0x0005, base_count>>8);
- mode_register = 0x4a; // single mode, increment, autoinit disable,
- // transfer type=read, channel 2
- outb(0x000b, mode_register);
- // port 81: DMA-1 Page Register, channel 2
- outb(0x0081, page);
- outb(0x000a, 0x02);
-
- // set up floppy controller for transfer
- floppy_prepare_controller(drive);
-
- // send format-track command (6 bytes) to controller
- outb(0x03f5, 0x4d); // 4d: format track
- outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
- outb(0x03f5, 2); // 512 byte sector size
- outb(0x03f5, num_sectors); // number of sectors per track
- outb(0x03f5, 0); // Gap length
- outb(0x03f5, 0xf6); // Fill byte
- // turn on interrupts
- ASM_START
- sti
- ASM_END
-
- // wait on 40:3e bit 7 to become 1
- do {
- val8 = read_byte(0x0040, 0x0040);
- if (val8 == 0) {
- floppy_reset_controller();
- SET_AH(0x80); // drive not ready (timeout)
- set_diskette_ret_status(0x80);
- SET_CF(); // error occurred
- return;
- }
- val8 = (read_byte(0x0040, 0x003e) & 0x80);
- } while ( val8 == 0 );
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
- ASM_START
- cli
- ASM_END
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0040, 0x003e);
- val8 &= 0x7f;
- write_byte(0x0040, 0x003e, val8);
- // check port 3f4 for accessibility to status bytes
- val8 = inb(0x3f4);
- if ( (val8 & 0xc0) != 0xc0 )
- BX_PANIC("int13_diskette: ctrl not ready\n");
-
- // read 7 return status bytes from controller
- // using loop index broken, have to unroll...
- return_status[0] = inb(0x3f5);
- return_status[1] = inb(0x3f5);
- return_status[2] = inb(0x3f5);
- return_status[3] = inb(0x3f5);
- return_status[4] = inb(0x3f5);
- return_status[5] = inb(0x3f5);
- return_status[6] = inb(0x3f5);
- // record in BIOS Data Area
- write_byte(0x0040, 0x0042, return_status[0]);
- write_byte(0x0040, 0x0043, return_status[1]);
- write_byte(0x0040, 0x0044, return_status[2]);
- write_byte(0x0040, 0x0045, return_status[3]);
- write_byte(0x0040, 0x0046, return_status[4]);
- write_byte(0x0040, 0x0047, return_status[5]);
- write_byte(0x0040, 0x0048, return_status[6]);
-
- if ( (return_status[0] & 0xc0) != 0 ) {
- if ( (return_status[1] & 0x02) != 0 ) {
- // diskette not writable.
- // AH=status code=0x03 (tried to write on write-protected disk)
- // AL=number of sectors written=0
- AX = 0x0300;
- SET_CF();
- return;
- } else {
- BX_PANIC("int13_diskette_function: write error\n");
- }
- }
-
- SET_AH(0);
- set_diskette_ret_status(0);
- set_diskette_current_cyl(drive, 0);
- CLEAR_CF(); // successful
- return;
-
-
- case 0x08: // read diskette drive parameters
-BX_DEBUG_INT13_FL("floppy f08\n");
- drive = GET_ELDL();
-
- if (drive > 1) {
- AX = 0;
- BX = 0;
- CX = 0;
- DX = 0;
- ES = 0;
- DI = 0;
- SET_DL(num_floppies);
- SET_CF();
- return;
- }
-
- drive_type = inb_cmos(0x10);
- num_floppies = 0;
- if (drive_type & 0xf0)
- num_floppies++;
- if (drive_type & 0x0f)
- num_floppies++;
-
- if (drive == 0)
- drive_type >>= 4;
- else
- drive_type &= 0x0f;
-
- SET_BH(0);
- SET_BL(drive_type);
- SET_AH(0);
- SET_AL(0);
- SET_DL(num_floppies);
-
- switch (drive_type) {
- case 0: // none
- CX = 0;
- SET_DH(0); // max head #
- break;
-
- case 1: // 360KB, 5.25"
- CX = 0x2709; // 40 tracks, 9 sectors
- SET_DH(1); // max head #
- break;
-
- case 2: // 1.2MB, 5.25"
- CX = 0x4f0f; // 80 tracks, 15 sectors
- SET_DH(1); // max head #
- break;
-
- case 3: // 720KB, 3.5"
- CX = 0x4f09; // 80 tracks, 9 sectors
- SET_DH(1); // max head #
- break;
-
- case 4: // 1.44MB, 3.5"
- CX = 0x4f12; // 80 tracks, 18 sectors
- SET_DH(1); // max head #
- break;
-
- case 5: // 2.88MB, 3.5"
- CX = 0x4f24; // 80 tracks, 36 sectors
- SET_DH(1); // max head #
- break;
-
- case 6: // 160k, 5.25"
- CX = 0x2708; // 40 tracks, 8 sectors
- SET_DH(0); // max head #
- break;
-
- case 7: // 180k, 5.25"
- CX = 0x2709; // 40 tracks, 9 sectors
- SET_DH(0); // max head #
- break;
-
- case 8: // 320k, 5.25"
- CX = 0x2708; // 40 tracks, 8 sectors
- SET_DH(1); // max head #
- break;
-
- default: // ?
- BX_PANIC("floppy: int13: bad floppy type\n");
- }
-
- /* set es & di to point to 11 byte diskette param table in ROM */
-ASM_START
- push bp
- mov bp, sp
- mov ax, #diskette_param_table2
- mov _int13_diskette_function.DI+2[bp], ax
- mov _int13_diskette_function.ES+2[bp], cs
- pop bp
-ASM_END
- CLEAR_CF(); // success
- /* disk status not changed upon success */
- return;
-
-
- case 0x15: // read diskette drive type
-BX_DEBUG_INT13_FL("floppy f15\n");
- drive = GET_ELDL();
- if (drive > 1) {
- SET_AH(0); // only 2 drives supported
- // set_diskette_ret_status here ???
- SET_CF();
- return;
- }
- drive_type = inb_cmos(0x10);
-
- if (drive == 0)
- drive_type >>= 4;
- else
- drive_type &= 0x0f;
- CLEAR_CF(); // successful, not present
- if (drive_type==0) {
- SET_AH(0); // drive not present
- }
- else {
- SET_AH(1); // drive present, does not support change line
- }
-
- return;
-
- case 0x16: // get diskette change line status
-BX_DEBUG_INT13_FL("floppy f16\n");
- drive = GET_ELDL();
- if (drive > 1) {
- SET_AH(0x01); // invalid drive
- set_diskette_ret_status(0x01);
- SET_CF();
- return;
- }
-
- SET_AH(0x06); // change line not supported
- set_diskette_ret_status(0x06);
- SET_CF();
- return;
-
- case 0x17: // set diskette type for format(old)
-BX_DEBUG_INT13_FL("floppy f17\n");
- /* not used for 1.44M floppies */
- SET_AH(0x01); // not supported
- set_diskette_ret_status(1); /* not supported */
- SET_CF();
- return;
-
- case 0x18: // set diskette type for format(new)
-BX_DEBUG_INT13_FL("floppy f18\n");
- SET_AH(0x01); // do later
- set_diskette_ret_status(1);
- SET_CF();
- return;
-
- default:
- BX_INFO("int13_diskette: unsupported AH=%02x\n", GET_AH());
-
- // if ( (ah==0x20) || ((ah>=0x41) && (ah<=0x49)) || (ah==0x4e) ) {
- SET_AH(0x01); // ???
- set_diskette_ret_status(1);
- SET_CF();
- return;
- // }
- }
-}
-#else // #if BX_SUPPORT_FLOPPY
- void
-int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit8u val8;
-
- switch ( GET_AH() ) {
-
- case 0x01: // Read Diskette Status
- CLEAR_CF();
- val8 = read_byte(0x0000, 0x0441);
- SET_AH(val8);
- if (val8) {
- SET_CF();
- }
- return;
-
- default:
- SET_CF();
- write_byte(0x0000, 0x0441, 0x01);
- SET_AH(0x01);
- }
-}
-#endif // #if BX_SUPPORT_FLOPPY
-
- void
-set_diskette_ret_status(value)
- Bit8u value;
-{
- write_byte(0x0040, 0x0041, value);
-}
-
- void
-set_diskette_current_cyl(drive, cyl)
- Bit8u drive;
- Bit8u cyl;
-{
- if (drive > 1)
- BX_PANIC("set_diskette_current_cyl(): drive > 1\n");
- write_byte(0x0040, 0x0094+drive, cyl);
-}
-
- void
-determine_floppy_media(drive)
- Bit16u drive;
-{
-#if 0
- Bit8u val8, DOR, ctrl_info;
-
- ctrl_info = read_byte(0x0040, 0x008F);
- if (drive==1)
- ctrl_info >>= 4;
- else
- ctrl_info &= 0x0f;
-
-#if 0
- if (drive == 0) {
- DOR = 0x1c; // DOR: drive0 motor on, DMA&int enabled, normal op, drive select 0
- }
- else {
- DOR = 0x2d; // DOR: drive1 motor on, DMA&int enabled, normal op, drive select 1
- }
-#endif
-
- if ( (ctrl_info & 0x04) != 0x04 ) {
- // Drive not determined means no drive exists, done.
- return;
- }
-
-#if 0
- // check Main Status Register for readiness
- val8 = inb(0x03f4) & 0x80; // Main Status Register
- if (val8 != 0x80)
- BX_PANIC("d_f_m: MRQ bit not set\n");
-
- // change line
-
- // existing BDA values
-
- // turn on drive motor
- outb(0x03f2, DOR); // Digital Output Register
- //
-#endif
- BX_PANIC("d_f_m: OK so far\n");
-#endif
-}
-
- void
-int17_function(regs, ds, iret_addr)
- pusha_regs_t regs; // regs pushed from PUSHA instruction
- Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper
- iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call
-{
- Bit16u addr,timeout;
- Bit8u val8;
-
- ASM_START
- sti
- ASM_END
-
- addr = read_word(0x0040, (regs.u.r16.dx << 1) + 8);
- if ((regs.u.r8.ah < 3) && (regs.u.r16.dx < 3) && (addr > 0)) {
- timeout = read_byte(0x0040, 0x0078 + regs.u.r16.dx) << 8;
- if (regs.u.r8.ah == 0) {
- outb(addr, regs.u.r8.al);
- val8 = inb(addr+2);
- outb(addr+2, val8 | 0x01); // send strobe
- ASM_START
- nop
- ASM_END
- outb(addr+2, val8 & ~0x01);
- while (((inb(addr+1) & 0x40) == 0x40) && (timeout)) {
- timeout--;
- }
- }
- if (regs.u.r8.ah == 1) {
- val8 = inb(addr+2);
- outb(addr+2, val8 & ~0x04); // send init
- ASM_START
- nop
- ASM_END
- outb(addr+2, val8 | 0x04);
- }
- val8 = inb(addr+1);
- regs.u.r8.ah = (val8 ^ 0x48);
- if (!timeout) regs.u.r8.ah |= 0x01;
- ClearCF(iret_addr.flags);
- } else {
- SetCF(iret_addr.flags); // Unsupported
- }
-}
-
-void
-int19_function(seq_nr)
-Bit16u seq_nr;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u bootdev;
- Bit8u bootdrv;
- Bit8u bootchk;
- Bit16u bootseg;
- Bit16u bootip;
- Bit16u status;
- Bit16u bootfirst;
-
- ipl_entry_t e;
-
- // if BX_ELTORITO_BOOT is not defined, old behavior
- // check bit 5 in CMOS reg 0x2d. load either 0x00 or 0x80 into DL
- // in preparation for the intial INT 13h (0=floppy A:, 0x80=C:)
- // 0: system boot sequence, first drive C: then A:
- // 1: system boot sequence, first drive A: then C:
- // else BX_ELTORITO_BOOT is defined
- // CMOS regs 0x3D and 0x38 contain the boot sequence:
- // CMOS reg 0x3D & 0x0f : 1st boot device
- // CMOS reg 0x3D & 0xf0 : 2nd boot device
- // CMOS reg 0x38 & 0xf0 : 3rd boot device
- // boot device codes:
- // 0x00 : not defined
- // 0x01 : first floppy
- // 0x02 : first harddrive
- // 0x03 : first cdrom
- // 0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot)
- // else : boot failure
-
- // Get the boot sequence
-#if BX_ELTORITO_BOOT
- bootdev = inb_cmos(0x3d);
- bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
- bootdev >>= 4 * seq_nr;
- bootdev &= 0xf;
-
- /* Read user selected device */
- bootfirst = read_word(IPL_SEG, IPL_BOOTFIRST_OFFSET);
- if (bootfirst != 0xFFFF) {
- bootdev = bootfirst;
- /* User selected device not set */
- write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF);
- /* Reset boot sequence */
- write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xFFFF);
- } else if (bootdev == 0) BX_PANIC("No bootable device.\n");
-
- /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
- bootdev -= 1;
-#else
- if (seq_nr ==2) BX_PANIC("No more boot devices.");
- if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1))
- /* Boot from floppy if the bit is set or it's the second boot */
- bootdev = 0x00;
- else
- bootdev = 0x01;
-#endif
-
- /* Read the boot device from the IPL table */
- if (get_boot_vector(bootdev, &e) == 0) {
- BX_INFO("Invalid boot device (0x%x)\n", bootdev);
- return;
- }
-
- /* Do the loading, and set up vector as a far pointer to the boot
- * address, and bootdrv as the boot drive */
- print_boot_device(&e);
-
- switch(e.type) {
- case IPL_TYPE_FLOPPY: /* FDD */
- case IPL_TYPE_HARDDISK: /* HDD */
-
- bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
- bootseg = 0x07c0;
- status = 0;
-
-ASM_START
- push bp
- mov bp, sp
- push ax
- push bx
- push cx
- push dx
-
- mov dl, _int19_function.bootdrv + 2[bp]
- mov ax, _int19_function.bootseg + 2[bp]
- mov es, ax ;; segment
- xor bx, bx ;; offset
- mov ah, #0x02 ;; function 2, read diskette sector
- mov al, #0x01 ;; read 1 sector
- mov ch, #0x00 ;; track 0
- mov cl, #0x01 ;; sector 1
- mov dh, #0x00 ;; head 0
- int #0x13 ;; read sector
- jnc int19_load_done
- mov ax, #0x0001
- mov _int19_function.status + 2[bp], ax
-
-int19_load_done:
- pop dx
- pop cx
- pop bx
- pop ax
- pop bp
-ASM_END
-
- if (status != 0) {
- print_boot_failure(e.type, 1);
- return;
- }
-
- /* Always check the signature on a HDD boot sector; on FDD, only do
- * the check if the CMOS doesn't tell us to skip it */
- if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) {
- if (read_word(bootseg,0x1fe) != 0xaa55) {
- print_boot_failure(e.type, 0);
- return;
- }
- }
-
- /* Canonicalize bootseg:bootip */
- bootip = (bootseg & 0x0fff) << 4;
- bootseg &= 0xf000;
- break;
-
-#if BX_ELTORITO_BOOT
- case IPL_TYPE_CDROM: /* CD-ROM */
- status = cdrom_boot();
-
- // If failure
- if ( (status & 0x00ff) !=0 ) {
- print_cdromboot_failure(status);
- print_boot_failure(e.type, 1);
- return;
- }
-
- bootdrv = (Bit8u)(status>>8);
- bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment);
- bootip = 0;
- break;
-#endif
-
- case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */
- bootseg = e.vector >> 16;
- bootip = e.vector & 0xffff;
- break;
-
- default: return;
- }
-
- /* Debugging info */
- BX_INFO("Booting from %x:%x\n", bootseg, bootip);
-
- /* Jump to the boot vector */
-ASM_START
- mov bp, sp
- push cs
- push #int18_handler
- ;; Build an iret stack frame that will take us to the boot vector.
- ;; iret pops ip, then cs, then flags, so push them in the opposite order.
- pushf
- mov ax, _int19_function.bootseg + 0[bp]
- push ax
- mov ax, _int19_function.bootip + 0[bp]
- push ax
- ;; Set the magic number in ax and the boot drive in dl.
- mov ax, #0xaa55
- mov dl, _int19_function.bootdrv + 0[bp]
- ;; Zero some of the other registers.
- xor bx, bx
- mov ds, bx
- mov es, bx
- mov bp, bx
- ;; Go!
- iret
-ASM_END
-}
-
- void
-int1a_function(regs, ds, iret_addr)
- pusha_regs_t regs; // regs pushed from PUSHA instruction
- Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper
- iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call
-{
- Bit8u val8;
-
- BX_DEBUG_INT1A("int1a: AX=%04x BX=%04x CX=%04x DX=%04x DS=%04x\n", regs.u.r16.ax, regs.u.r16.bx, regs.u.r16.cx, regs.u.r16.dx, ds);
-
- ASM_START
- sti
- ASM_END
-
- switch (regs.u.r8.ah) {
- case 0: // get current clock count
- ASM_START
- cli
- ASM_END
- regs.u.r16.cx = BiosData->ticks_high;
- regs.u.r16.dx = BiosData->ticks_low;
- regs.u.r8.al = BiosData->midnight_flag;
- BiosData->midnight_flag = 0; // reset flag
- ASM_START
- sti
- ASM_END
- // AH already 0
- ClearCF(iret_addr.flags); // OK
- break;
-
- case 1: // Set Current Clock Count
- ASM_START
- cli
- ASM_END
- BiosData->ticks_high = regs.u.r16.cx;
- BiosData->ticks_low = regs.u.r16.dx;
- BiosData->midnight_flag = 0; // reset flag
- ASM_START
- sti
- ASM_END
- regs.u.r8.ah = 0;
- ClearCF(iret_addr.flags); // OK
- break;
-
-
- case 2: // Read CMOS Time
- if (rtc_updating()) {
- SetCF(iret_addr.flags);
- break;
- }
-
- regs.u.r8.dh = inb_cmos(0x00); // Seconds
- regs.u.r8.cl = inb_cmos(0x02); // Minutes
- regs.u.r8.ch = inb_cmos(0x04); // Hours
- regs.u.r8.dl = inb_cmos(0x0b) & 0x01; // Stat Reg B
- regs.u.r8.ah = 0;
- regs.u.r8.al = regs.u.r8.ch;
- ClearCF(iret_addr.flags); // OK
- break;
-
- case 3: // Set CMOS Time
- // Using a debugger, I notice the following masking/setting
- // of bits in Status Register B, by setting Reg B to
- // a few values and getting its value after INT 1A was called.
- //
- // try#1 try#2 try#3
- // before 1111 1101 0111 1101 0000 0000
- // after 0110 0010 0110 0010 0000 0010
- //
- // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
- // My assumption: RegB = ((RegB & 01100000b) | 00000010b)
- if (rtc_updating()) {
- init_rtc();
- // fall through as if an update were not in progress
- }
- outb_cmos(0x00, regs.u.r8.dh); // Seconds
- outb_cmos(0x02, regs.u.r8.cl); // Minutes
- outb_cmos(0x04, regs.u.r8.ch); // Hours
- // Set Daylight Savings time enabled bit to requested value
- val8 = (inb_cmos(0x0b) & 0x60) | 0x02 | (regs.u.r8.dl & 0x01);
- // (reg B already selected)
- outb_cmos(0x0b, val8);
- regs.u.r8.ah = 0;
- regs.u.r8.al = val8; // val last written to Reg B
- ClearCF(iret_addr.flags); // OK
- break;
-
- case 4: // Read CMOS Date
- regs.u.r8.ah = 0;
- if (rtc_updating()) {
- SetCF(iret_addr.flags);
- break;
- }
- regs.u.r8.cl = inb_cmos(0x09); // Year
- regs.u.r8.dh = inb_cmos(0x08); // Month
- regs.u.r8.dl = inb_cmos(0x07); // Day of Month
- regs.u.r8.ch = inb_cmos(0x32); // Century
- regs.u.r8.al = regs.u.r8.ch;
- ClearCF(iret_addr.flags); // OK
- break;
-
- case 5: // Set CMOS Date
- // Using a debugger, I notice the following masking/setting
- // of bits in Status Register B, by setting Reg B to
- // a few values and getting its value after INT 1A was called.
- //
- // try#1 try#2 try#3 try#4
- // before 1111 1101 0111 1101 0000 0010 0000 0000
- // after 0110 1101 0111 1101 0000 0010 0000 0000
- //
- // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
- // My assumption: RegB = (RegB & 01111111b)
- if (rtc_updating()) {
- init_rtc();
- SetCF(iret_addr.flags);
- break;
- }
- outb_cmos(0x09, regs.u.r8.cl); // Year
- outb_cmos(0x08, regs.u.r8.dh); // Month
- outb_cmos(0x07, regs.u.r8.dl); // Day of Month
- outb_cmos(0x32, regs.u.r8.ch); // Century
- val8 = inb_cmos(0x0b) & 0x7f; // clear halt-clock bit
- outb_cmos(0x0b, val8);
- regs.u.r8.ah = 0;
- regs.u.r8.al = val8; // AL = val last written to Reg B
- ClearCF(iret_addr.flags); // OK
- break;
-
- case 6: // Set Alarm Time in CMOS
- // Using a debugger, I notice the following masking/setting
- // of bits in Status Register B, by setting Reg B to
- // a few values and getting its value after INT 1A was called.
- //
- // try#1 try#2 try#3
- // before 1101 1111 0101 1111 0000 0000
- // after 0110 1111 0111 1111 0010 0000
- //
- // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
- // My assumption: RegB = ((RegB & 01111111b) | 00100000b)
- val8 = inb_cmos(0x0b); // Get Status Reg B
- regs.u.r16.ax = 0;
- if (val8 & 0x20) {
- // Alarm interrupt enabled already
- SetCF(iret_addr.flags); // Error: alarm in use
- break;
- }
- if (rtc_updating()) {
- init_rtc();
- // fall through as if an update were not in progress
- }
- outb_cmos(0x01, regs.u.r8.dh); // Seconds alarm
- outb_cmos(0x03, regs.u.r8.cl); // Minutes alarm
- outb_cmos(0x05, regs.u.r8.ch); // Hours alarm
- outb(0xa1, inb(0xa1) & 0xfe); // enable IRQ 8
- // enable Status Reg B alarm bit, clear halt clock bit
- outb_cmos(0x0b, (val8 & 0x7f) | 0x20);
- ClearCF(iret_addr.flags); // OK
- break;
-
- case 7: // Turn off Alarm
- // Using a debugger, I notice the following masking/setting
- // of bits in Status Register B, by setting Reg B to
- // a few values and getting its value after INT 1A was called.
- //
- // try#1 try#2 try#3 try#4
- // before 1111 1101 0111 1101 0010 0000 0010 0010
- // after 0100 0101 0101 0101 0000 0000 0000 0010
- //
- // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
- // My assumption: RegB = (RegB & 01010111b)
- val8 = inb_cmos(0x0b); // Get Status Reg B
- // clear clock-halt bit, disable alarm bit
- outb_cmos(0x0b, val8 & 0x57); // disable alarm bit
- regs.u.r8.ah = 0;
- regs.u.r8.al = val8; // val last written to Reg B
- ClearCF(iret_addr.flags); // OK
- break;
-#if BX_PCIBIOS
- case 0xb1:
- // real mode PCI BIOS functions now handled in assembler code
- // this C code handles the error code for information only
- if (regs.u.r8.bl == 0xff) {
- BX_INFO("PCI BIOS: PCI not present\n");
- } else if (regs.u.r8.bl == 0x81) {
- BX_INFO("unsupported PCI BIOS function 0x%02x\n", regs.u.r8.al);
- } else if (regs.u.r8.bl == 0x83) {
- BX_INFO("bad PCI vendor ID %04x\n", regs.u.r16.dx);
- } else if (regs.u.r8.bl == 0x86) {
- if (regs.u.r8.al == 0x02) {
- BX_INFO("PCI device %04x:%04x not found at index %d\n", regs.u.r16.dx, regs.u.r16.cx, regs.u.r16.si);
- } else {
- BX_INFO("no PCI device with class code 0x%02x%04x found at index %d\n", regs.u.r8.cl, regs.u.r16.dx, regs.u.r16.si);
- }
- }
- regs.u.r8.ah = regs.u.r8.bl;
- SetCF(iret_addr.flags);
- break;
-#endif
-
- default:
- SetCF(iret_addr.flags); // Unsupported
- }
-}
-
- void
-int70_function(regs, ds, iret_addr)
- pusha_regs_t regs; // regs pushed from PUSHA instruction
- Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper
- iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call
-{
- // INT 70h: IRQ 8 - CMOS RTC interrupt from periodic or alarm modes
- Bit8u registerB = 0, registerC = 0;
-
- // Check which modes are enabled and have occurred.
- registerB = inb_cmos( 0xB );
- registerC = inb_cmos( 0xC );
-
- if( ( registerB & 0x60 ) != 0 ) {
- if( ( registerC & 0x20 ) != 0 ) {
- // Handle Alarm Interrupt.
-ASM_START
- sti
- int #0x4a
- cli
-ASM_END
- }
- if( ( registerC & 0x40 ) != 0 ) {
- // Handle Periodic Interrupt.
-
- if( read_byte( 0x40, 0xA0 ) != 0 ) {
- // Wait Interval (Int 15, AH=83) active.
- Bit32u time, toggle;
-
- time = read_dword( 0x40, 0x9C ); // Time left in microseconds.
- if( time < 0x3D1 ) {
- // Done waiting.
- Bit16u segment, offset;
-
- segment = read_word( 0x40, 0x98 );
- offset = read_word( 0x40, 0x9A );
- write_byte( 0x40, 0xA0, 0 ); // Turn of status byte.
- outb_cmos( 0xB, registerB & 0x37 ); // Clear the Periodic Interrupt.
- write_byte(segment, offset, read_byte(segment, offset) | 0x80 ); // Write to specified flag byte.
- } else {
- // Continue waiting.
- time -= 0x3D1;
- write_dword( 0x40, 0x9C, time );
- }
- }
- }
- }
-
-ASM_START
- call eoi_both_pics
-ASM_END
-}
-
-
-ASM_START
-;------------------------------------------
-;- INT74h : PS/2 mouse hardware interrupt -
-;------------------------------------------
-int74_handler:
- sti
- pusha
- push ds ;; save DS
- push #0x00 ;; placeholder for status
- push #0x00 ;; placeholder for X
- push #0x00 ;; placeholder for Y
- push #0x00 ;; placeholder for Z
- push #0x00 ;; placeholder for make_far_call boolean
- call _int74_function
- pop cx ;; remove make_far_call from stack
- jcxz int74_done
-
- ;; make far call to EBDA:0022
- push #0x00
- pop ds
- push 0x040E ;; push 0000:040E (opcodes 0xff, 0x36, 0x0E, 0x04)
- pop ds
- //CALL_EP(0x0022) ;; call far routine (call_Ep DS:0022 :opcodes 0xff, 0x1e, 0x22, 0x00)
- call far ptr[0x22]
-int74_done:
- cli
- call eoi_both_pics
- add sp, #8 ;; pop status, x, y, z
-
- pop ds ;; restore DS
- popa
- iret
-
-
-;; This will perform an IRET, but will retain value of current CF
-;; by altering flags on stack. Better than RETF #02.
-iret_modify_cf:
- jc carry_set
- push bp
- mov bp, sp
- and BYTE [bp + 0x06], #0xfe
- pop bp
- iret
-carry_set:
- push bp
- mov bp, sp
- or BYTE [bp + 0x06], #0x01
- pop bp
- iret
-
-
-;----------------------
-;- INT13h (relocated) -
-;----------------------
-;
-; int13_relocated is a little bit messed up since I played with it
-; I have to rewrite it:
-; - call a function that detect which function to call
-; - make all called C function get the same parameters list
-;
-int13_relocated:
-
-#if BX_ELTORITO_BOOT
- ;; check for an eltorito function
- cmp ah,#0x4a
- jb int13_not_eltorito
- cmp ah,#0x4d
- ja int13_not_eltorito
-
- pusha
- push es
- push ds
- push ss
- pop ds
-
- push #int13_out
- jmp _int13_eltorito ;; ELDX not used
-
-int13_not_eltorito:
- push ax
- push bx
- push cx
- push dx
-
- ;; check if emulation active
- call _cdemu_isactive
- cmp al,#0x00
- je int13_cdemu_inactive
-
- ;; check if access to the emulated drive
- call _cdemu_emulated_drive
- pop dx
- push dx
- cmp al,dl ;; int13 on emulated drive
- jne int13_nocdemu
-
- pop dx
- pop cx
- pop bx
- pop ax
-
- pusha
- push es
- push ds
- push ss
- pop ds
-
- push #int13_out
- jmp _int13_cdemu ;; ELDX not used
-
-int13_nocdemu:
- and dl,#0xE0 ;; mask to get device class, including cdroms
- cmp al,dl ;; al is 0x00 or 0x80
- jne int13_cdemu_inactive ;; inactive for device class
-
- pop dx
- pop cx
- pop bx
- pop ax
-
- push ax
- push cx
- push dx
- push bx
-
- dec dl ;; real drive is dl - 1
- jmp int13_legacy
-
-int13_cdemu_inactive:
- pop dx
- pop cx
- pop bx
- pop ax
-
-#endif // BX_ELTORITO_BOOT
-
-int13_noeltorito:
-
- push ax
- push cx
- push dx
- push bx
-
-int13_legacy:
-
- push dx ;; push eltorito value of dx instead of sp
-
- push bp
- push si
- push di
-
- push es
- push ds
- push ss
- pop ds
-
- ;; now the 16-bit registers can be restored with:
- ;; pop ds; pop es; popa; iret
- ;; arguments passed to functions should be
- ;; DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS
-
- test dl, #0x80
- jnz int13_notfloppy
-
- push #int13_out
- jmp _int13_diskette_function
-
-int13_notfloppy:
-
-#if BX_USE_ATADRV
-
- cmp dl, #0xE0
- jb int13_notcdrom
-
- // ebx is modified: BSD 5.2.1 boot loader problem
- // someone should figure out which 32 bit register that actually are used
-
- shr ebx, #16
- push bx
-
- call _int13_cdrom
-
- pop bx
- shl ebx, #16
-
- jmp int13_out
-
-int13_notcdrom:
-
-#endif
-
-int13_disk:
- ;; int13_harddisk modifies high word of EAX
- shr eax, #16
- push ax
- call _int13_harddisk
- pop ax
- shl eax, #16
-
-int13_out:
- pop ds
- pop es
- popa
- iret
-
-;----------
-;- INT18h -
-;----------
-int18_handler: ;; Boot Failure recovery: try the next device.
-
- ;; Reset SP and SS
- mov ax, #0xfffe
- mov sp, ax
- xor ax, ax
- mov ss, ax
-
- ;; Get the boot sequence number out of the IPL memory
- mov bx, #IPL_SEG
- mov ds, bx ;; Set segment
- mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number
- inc bx ;; ++
- mov IPL_SEQUENCE_OFFSET, bx ;; Write it back
- mov ds, ax ;; and reset the segment to zero.
-
- ;; Carry on in the INT 19h handler, using the new sequence number
- push bx
-
- jmp int19_next_boot
-
-;----------
-;- INT19h -
-;----------
-int19_relocated: ;; Boot function, relocated
-
- ;; int19 was beginning to be really complex, so now it
- ;; just calls a C function that does the work
-
- push bp
- mov bp, sp
-
- ;; Reset SS and SP
- mov ax, #0xfffe
- mov sp, ax
- xor ax, ax
- mov ss, ax
-
- ;; Start from the first boot device (0, in AX)
- mov bx, #IPL_SEG
- mov ds, bx ;; Set segment to write to the IPL memory
- mov IPL_SEQUENCE_OFFSET, ax ;; Save the sequence number
- mov ds, ax ;; and reset the segment.
-
- push ax
-
-int19_next_boot:
-
- ;; Call the C code for the next boot device
- call _int19_function
-
- ;; Boot failed: invoke the boot recovery function
- int #0x18
-
-;----------
-;- INT1Ch -
-;----------
-int1c_handler: ;; User Timer Tick
- iret
-
-
-;----------------------
-;- POST: Floppy Drive -
-;----------------------
-floppy_drive_post:
- xor ax, ax
- mov ds, ax
-
- mov al, #0x00
- mov 0x043e, al ;; drive 0 & 1 uncalibrated, no interrupt has occurred
-
- mov 0x043f, al ;; diskette motor status: read op, drive0, motors off
-
- mov 0x0440, al ;; diskette motor timeout counter: not active
- mov 0x0441, al ;; diskette controller status return code
-
- mov 0x0442, al ;; disk & diskette controller status register 0
- mov 0x0443, al ;; diskette controller status register 1
- mov 0x0444, al ;; diskette controller status register 2
- mov 0x0445, al ;; diskette controller cylinder number
- mov 0x0446, al ;; diskette controller head number
- mov 0x0447, al ;; diskette controller sector number
- mov 0x0448, al ;; diskette controller bytes written
-
- mov 0x048b, al ;; diskette configuration data
-
- ;; -----------------------------------------------------------------
- ;; (048F) diskette controller information
- ;;
- mov al, #0x10 ;; get CMOS diskette drive type
- out 0x70, AL
- in AL, 0x71
- mov ah, al ;; save byte to AH
-
-look_drive0:
- shr al, #4 ;; look at top 4 bits for drive 0
- jz f0_missing ;; jump if no drive0
- mov bl, #0x07 ;; drive0 determined, multi-rate, has changed line
- jmp look_drive1
-f0_missing:
- mov bl, #0x00 ;; no drive0
-
-look_drive1:
- mov al, ah ;; restore from AH
- and al, #0x0f ;; look at bottom 4 bits for drive 1
- jz f1_missing ;; jump if no drive1
- or bl, #0x70 ;; drive1 determined, multi-rate, has changed line
-f1_missing:
- ;; leave high bits in BL zerod
- mov 0x048f, bl ;; put new val in BDA (diskette controller information)
- ;; -----------------------------------------------------------------
-
- mov al, #0x00
- mov 0x0490, al ;; diskette 0 media state
- mov 0x0491, al ;; diskette 1 media state
-
- ;; diskette 0,1 operational starting state
- ;; drive type has not been determined,
- ;; has no changed detection line
- mov 0x0492, al
- mov 0x0493, al
-
- mov 0x0494, al ;; diskette 0 current cylinder
- mov 0x0495, al ;; diskette 1 current cylinder
-
- mov al, #0x02
- out #0x0a, al ;; clear DMA-1 channel 2 mask bit
-
- SET_INT_VECTOR(0x1E, #0xF000, #diskette_param_table2)
- SET_INT_VECTOR(0x40, #0xF000, #int13_diskette)
- SET_INT_VECTOR(0x0E, #0xF000, #int0e_handler) ;; IRQ 6
-
- ret
-
-
-;--------------------
-;- POST: HARD DRIVE -
-;--------------------
-; relocated here because the primary POST area isnt big enough.
-hard_drive_post:
- // IRQ 14 = INT 76h
- // INT 76h calls INT 15h function ax=9100
-
- mov al, #0x0a ; 0000 1010 = reserved, disable IRQ 14
- mov dx, #0x03f6
- out dx, al
-
- xor ax, ax
- mov ds, ax
- mov 0x0474, al /* hard disk status of last operation */
- mov 0x0477, al /* hard disk port offset (XT only ???) */
- mov 0x048c, al /* hard disk status register */
- mov 0x048d, al /* hard disk error register */
- mov 0x048e, al /* hard disk task complete flag */
- mov al, #0x01
- mov 0x0475, al /* hard disk number attached */
- mov al, #0xc0
- mov 0x0476, al /* hard disk control byte */
- SET_INT_VECTOR(0x13, #0xF000, #int13_handler)
- SET_INT_VECTOR(0x76, #0xF000, #int76_handler)
- ;; INT 41h: hard disk 0 configuration pointer
- ;; INT 46h: hard disk 1 configuration pointer
- SET_INT_VECTOR(0x41, #EBDA_SEG, #0x003D)
- SET_INT_VECTOR(0x46, #EBDA_SEG, #0x004D)
-
- ;; move disk geometry data from CMOS to EBDA disk parameter table(s)
- mov al, #0x12
- out #0x70, al
- in al, #0x71
- and al, #0xf0
- cmp al, #0xf0
- je post_d0_extended
- jmp check_for_hd1
-post_d0_extended:
- mov al, #0x19
- out #0x70, al
- in al, #0x71
- cmp al, #47 ;; decimal 47 - user definable
- je post_d0_type47
- HALT(__LINE__)
-post_d0_type47:
- ;; CMOS purpose param table offset
- ;; 1b cylinders low 0
- ;; 1c cylinders high 1
- ;; 1d heads 2
- ;; 1e write pre-comp low 5
- ;; 1f write pre-comp high 6
- ;; 20 retries/bad map/heads>8 8
- ;; 21 landing zone low C
- ;; 22 landing zone high D
- ;; 23 sectors/track E
-
- mov ax, #EBDA_SEG
- mov ds, ax
-
- ;;; Filling EBDA table for hard disk 0.
- mov al, #0x1f
- out #0x70, al
- in al, #0x71
- mov ah, al
- mov al, #0x1e
- out #0x70, al
- in al, #0x71
- mov (0x003d + 0x05), ax ;; write precomp word
-
- mov al, #0x20
- out #0x70, al
- in al, #0x71
- mov (0x003d + 0x08), al ;; drive control byte
-
- mov al, #0x22
- out #0x70, al
- in al, #0x71
- mov ah, al
- mov al, #0x21
- out #0x70, al
- in al, #0x71
- mov (0x003d + 0x0C), ax ;; landing zone word
-
- mov al, #0x1c ;; get cylinders word in AX
- out #0x70, al
- in al, #0x71 ;; high byte
- mov ah, al
- mov al, #0x1b
- out #0x70, al
- in al, #0x71 ;; low byte
- mov bx, ax ;; BX = cylinders
-
- mov al, #0x1d
- out #0x70, al
- in al, #0x71
- mov cl, al ;; CL = heads
-
- mov al, #0x23
- out #0x70, al
- in al, #0x71
- mov dl, al ;; DL = sectors
-
- cmp bx, #1024
- jnbe hd0_post_logical_chs ;; if cylinders > 1024, use translated style CHS
-
-hd0_post_physical_chs:
- ;; no logical CHS mapping used, just physical CHS
- ;; use Standard Fixed Disk Parameter Table (FDPT)
- mov (0x003d + 0x00), bx ;; number of physical cylinders
- mov (0x003d + 0x02), cl ;; number of physical heads
- mov (0x003d + 0x0E), dl ;; number of physical sectors
- jmp check_for_hd1
-
-hd0_post_logical_chs:
- ;; complies with Phoenix style Translated Fixed Disk Parameter Table (FDPT)
- mov (0x003d + 0x09), bx ;; number of physical cylinders
- mov (0x003d + 0x0b), cl ;; number of physical heads
- mov (0x003d + 0x04), dl ;; number of physical sectors
- mov (0x003d + 0x0e), dl ;; number of logical sectors (same)
- mov al, #0xa0
- mov (0x003d + 0x03), al ;; A0h signature, indicates translated table
-
- cmp bx, #2048
- jnbe hd0_post_above_2048
- ;; 1024 < c <= 2048 cylinders
- shr bx, #0x01
- shl cl, #0x01
- jmp hd0_post_store_logical
-
-hd0_post_above_2048:
- cmp bx, #4096
- jnbe hd0_post_above_4096
- ;; 2048 < c <= 4096 cylinders
- shr bx, #0x02
- shl cl, #0x02
- jmp hd0_post_store_logical
-
-hd0_post_above_4096:
- cmp bx, #8192
- jnbe hd0_post_above_8192
- ;; 4096 < c <= 8192 cylinders
- shr bx, #0x03
- shl cl, #0x03
- jmp hd0_post_store_logical
-
-hd0_post_above_8192:
- ;; 8192 < c <= 16384 cylinders
- shr bx, #0x04
- shl cl, #0x04
-
-hd0_post_store_logical:
- mov (0x003d + 0x00), bx ;; number of physical cylinders
- mov (0x003d + 0x02), cl ;; number of physical heads
- ;; checksum
- mov cl, #0x0f ;; repeat count
- mov si, #0x003d ;; offset to disk0 FDPT
- mov al, #0x00 ;; sum
-hd0_post_checksum_loop:
- add al, [si]
- inc si
- dec cl
- jnz hd0_post_checksum_loop
- not al ;; now take 2s complement
- inc al
- mov [si], al
-;;; Done filling EBDA table for hard disk 0.
-
-
-check_for_hd1:
- ;; is there really a second hard disk? if not, return now
- mov al, #0x12
- out #0x70, al
- in al, #0x71
- and al, #0x0f
- jnz post_d1_exists
- ret
-post_d1_exists:
- ;; check that the hd type is really 0x0f.
- cmp al, #0x0f
- jz post_d1_extended
- HALT(__LINE__)
-post_d1_extended:
- ;; check that the extended type is 47 - user definable
- mov al, #0x1a
- out #0x70, al
- in al, #0x71
- cmp al, #47 ;; decimal 47 - user definable
- je post_d1_type47
- HALT(__LINE__)
-post_d1_type47:
- ;; Table for disk1.
- ;; CMOS purpose param table offset
- ;; 0x24 cylinders low 0
- ;; 0x25 cylinders high 1
- ;; 0x26 heads 2
- ;; 0x27 write pre-comp low 5
- ;; 0x28 write pre-comp high 6
- ;; 0x29 heads>8 8
- ;; 0x2a landing zone low C
- ;; 0x2b landing zone high D
- ;; 0x2c sectors/track E
-;;; Fill EBDA table for hard disk 1.
- mov ax, #EBDA_SEG
- mov ds, ax
- mov al, #0x28
- out #0x70, al
- in al, #0x71
- mov ah, al
- mov al, #0x27
- out #0x70, al
- in al, #0x71
- mov (0x004d + 0x05), ax ;; write precomp word
-
- mov al, #0x29
- out #0x70, al
- in al, #0x71
- mov (0x004d + 0x08), al ;; drive control byte
-
- mov al, #0x2b
- out #0x70, al
- in al, #0x71
- mov ah, al
- mov al, #0x2a
- out #0x70, al
- in al, #0x71
- mov (0x004d + 0x0C), ax ;; landing zone word
-
- mov al, #0x25 ;; get cylinders word in AX
- out #0x70, al
- in al, #0x71 ;; high byte
- mov ah, al
- mov al, #0x24
- out #0x70, al
- in al, #0x71 ;; low byte
- mov bx, ax ;; BX = cylinders
-
- mov al, #0x26
- out #0x70, al
- in al, #0x71
- mov cl, al ;; CL = heads
-
- mov al, #0x2c
- out #0x70, al
- in al, #0x71
- mov dl, al ;; DL = sectors
-
- cmp bx, #1024
- jnbe hd1_post_logical_chs ;; if cylinders > 1024, use translated style CHS
-
-hd1_post_physical_chs:
- ;; no logical CHS mapping used, just physical CHS
- ;; use Standard Fixed Disk Parameter Table (FDPT)
- mov (0x004d + 0x00), bx ;; number of physical cylinders
- mov (0x004d + 0x02), cl ;; number of physical heads
- mov (0x004d + 0x0E), dl ;; number of physical sectors
- ret
-
-hd1_post_logical_chs:
- ;; complies with Phoenix style Translated Fixed Disk Parameter Table (FDPT)
- mov (0x004d + 0x09), bx ;; number of physical cylinders
- mov (0x004d + 0x0b), cl ;; number of physical heads
- mov (0x004d + 0x04), dl ;; number of physical sectors
- mov (0x004d + 0x0e), dl ;; number of logical sectors (same)
- mov al, #0xa0
- mov (0x004d + 0x03), al ;; A0h signature, indicates translated table
-
- cmp bx, #2048
- jnbe hd1_post_above_2048
- ;; 1024 < c <= 2048 cylinders
- shr bx, #0x01
- shl cl, #0x01
- jmp hd1_post_store_logical
-
-hd1_post_above_2048:
- cmp bx, #4096
- jnbe hd1_post_above_4096
- ;; 2048 < c <= 4096 cylinders
- shr bx, #0x02
- shl cl, #0x02
- jmp hd1_post_store_logical
-
-hd1_post_above_4096:
- cmp bx, #8192
- jnbe hd1_post_above_8192
- ;; 4096 < c <= 8192 cylinders
- shr bx, #0x03
- shl cl, #0x03
- jmp hd1_post_store_logical
-
-hd1_post_above_8192:
- ;; 8192 < c <= 16384 cylinders
- shr bx, #0x04
- shl cl, #0x04
-
-hd1_post_store_logical:
- mov (0x004d + 0x00), bx ;; number of physical cylinders
- mov (0x004d + 0x02), cl ;; number of physical heads
- ;; checksum
- mov cl, #0x0f ;; repeat count
- mov si, #0x004d ;; offset to disk0 FDPT
- mov al, #0x00 ;; sum
-hd1_post_checksum_loop:
- add al, [si]
- inc si
- dec cl
- jnz hd1_post_checksum_loop
- not al ;; now take 2s complement
- inc al
- mov [si], al
-;;; Done filling EBDA table for hard disk 1.
-
- ret
-
-;--------------------
-;- POST: EBDA segment
-;--------------------
-; relocated here because the primary POST area isnt big enough.
-ebda_post:
-#if BX_USE_EBDA
- mov ax, #EBDA_SEG
- mov ds, ax
- mov byte ptr [0x0], #EBDA_SIZE
-#endif
- xor ax, ax ; mov EBDA seg into 40E
- mov ds, ax
- mov word ptr [0x40E], #EBDA_SEG
- ret;;
-
-;--------------------
-;- POST: EOI + jmp via [0x40:67)
-;--------------------
-; relocated here because the primary POST area isnt big enough.
-eoi_jmp_post:
- mov al, #0x20
- out #0xA0, al ;; slave PIC EOI
- mov al, #0x20
- out #0x20, al ;; master PIC EOI
-
-jmp_post_0x467:
- xor ax, ax
- mov ds, ax
-
- jmp far ptr [0x467]
-
-iret_post_0x467:
- xor ax, ax
- mov ds, ax
-
- mov sp, [0x467]
- mov ss, [0x469]
- iret
-
-retf_post_0x467:
- xor ax, ax
- mov ds, ax
-
- mov sp, [0x467]
- mov ss, [0x469]
- retf
-
-s3_post:
- mov sp, #0xffe
-#if BX_ROMBIOS32
- call rombios32_init
-#endif
- call _s3_resume
- mov bl, #0x00
- and ax, ax
- jz normal_post
- call _s3_resume_panic
-
-;--------------------
-eoi_both_pics:
- mov al, #0x20
- out #0xA0, al ;; slave PIC EOI
-eoi_master_pic:
- mov al, #0x20
- out #0x20, al ;; master PIC EOI
- ret
-
-;--------------------
-BcdToBin:
- ;; in: AL in BCD format
- ;; out: AL in binary format, AH will always be 0
- ;; trashes BX
- mov bl, al
- and bl, #0x0f ;; bl has low digit
- shr al, #4 ;; al has high digit
- mov bh, #10
- mul al, bh ;; multiply high digit by 10 (result in AX)
- add al, bl ;; then add low digit
- ret
-
-;--------------------
-timer_tick_post:
- ;; Setup the Timer Ticks Count (0x46C:dword) and
- ;; Timer Ticks Roller Flag (0x470:byte)
- ;; The Timer Ticks Count needs to be set according to
- ;; the current CMOS time, as if ticks have been occurring
- ;; at 18.2hz since midnight up to this point. Calculating
- ;; this is a little complicated. Here are the factors I gather
- ;; regarding this. 14,318,180 hz was the original clock speed,
- ;; chosen so it could be divided by either 3 to drive the 5Mhz CPU
- ;; at the time, or 4 to drive the CGA video adapter. The div3
- ;; source was divided again by 4 to feed a 1.193Mhz signal to
- ;; the timer. With a maximum 16bit timer count, this is again
- ;; divided down by 65536 to 18.2hz.
- ;;
- ;; 14,318,180 Hz clock
- ;; /3 = 4,772,726 Hz fed to orginal 5Mhz CPU
- ;; /4 = 1,193,181 Hz fed to timer
- ;; /65536 (maximum timer count) = 18.20650736 ticks/second
- ;; 1 second = 18.20650736 ticks
- ;; 1 minute = 1092.390442 ticks
- ;; 1 hour = 65543.42651 ticks
- ;;
- ;; Given the values in the CMOS clock, one could calculate
- ;; the number of ticks by the following:
- ;; ticks = (BcdToBin(seconds) * 18.206507) +
- ;; (BcdToBin(minutes) * 1092.3904)
- ;; (BcdToBin(hours) * 65543.427)
- ;; To get a little more accuracy, since Im using integer
- ;; arithmatic, I use:
- ;; ticks = (BcdToBin(seconds) * 18206507) / 1000000 +
- ;; (BcdToBin(minutes) * 10923904) / 10000 +
- ;; (BcdToBin(hours) * 65543427) / 1000
-
- ;; assuming DS=0000
-
- ;; get CMOS seconds
- xor eax, eax ;; clear EAX
- mov al, #0x00
- out #0x70, al
- in al, #0x71 ;; AL has CMOS seconds in BCD
- call BcdToBin ;; EAX now has seconds in binary
- mov edx, #18206507
- mul eax, edx
- mov ebx, #1000000
- xor edx, edx
- div eax, ebx
- mov ecx, eax ;; ECX will accumulate total ticks
-
- ;; get CMOS minutes
- xor eax, eax ;; clear EAX
- mov al, #0x02
- out #0x70, al
- in al, #0x71 ;; AL has CMOS minutes in BCD
- call BcdToBin ;; EAX now has minutes in binary
- mov edx, #10923904
- mul eax, edx
- mov ebx, #10000
- xor edx, edx
- div eax, ebx
- add ecx, eax ;; add to total ticks
-
- ;; get CMOS hours
- xor eax, eax ;; clear EAX
- mov al, #0x04
- out #0x70, al
- in al, #0x71 ;; AL has CMOS hours in BCD
- call BcdToBin ;; EAX now has hours in binary
- mov edx, #65543427
- mul eax, edx
- mov ebx, #1000
- xor edx, edx
- div eax, ebx
- add ecx, eax ;; add to total ticks
-
- mov 0x46C, ecx ;; Timer Ticks Count
- xor al, al
- mov 0x470, al ;; Timer Ticks Rollover Flag
- ret
-
-;--------------------
-int76_handler:
- ;; record completion in BIOS task complete flag
- push ax
- push ds
- mov ax, #0x0040
- mov ds, ax
- mov 0x008E, #0xff
- call eoi_both_pics
- pop ds
- pop ax
- iret
-
-
-;--------------------
-#if BX_APM
-
-use32 386
-#define APM_PROT32
-#include "apmbios.S"
-
-use16 386
-#define APM_PROT16
-#include "apmbios.S"
-
-#define APM_REAL
-#include "apmbios.S"
-
-#endif
-
-;--------------------
-#if BX_PCIBIOS
-use32 386
-.align 16
-bios32_structure:
- db 0x5f, 0x33, 0x32, 0x5f ;; "_32_" signature
- dw bios32_entry_point, 0xf ;; 32 bit physical address
- db 0 ;; revision level
- ;; length in paragraphs and checksum stored in a word to prevent errors
- dw (~(((bios32_entry_point >> 8) + (bios32_entry_point & 0xff) + 0x32) \
- & 0xff) << 8) + 0x01
- db 0,0,0,0,0 ;; reserved
-
-.align 16
-bios32_entry_point:
- pushfd
- cmp eax, #0x49435024 ;; "$PCI"
- jne unknown_service
- mov eax, #0x80000000
- mov dx, #0x0cf8
- out dx, eax
- mov dx, #0x0cfc
- in eax, dx
-#ifdef PCI_FIXED_HOST_BRIDGE
- cmp eax, #PCI_FIXED_HOST_BRIDGE
- jne unknown_service
-#else
- ;; say ok if a device is present
- cmp eax, #0xffffffff
- je unknown_service
-#endif
- mov ebx, #0x000f0000
- mov ecx, #0
- mov edx, #pcibios_protected
- xor al, al
- jmp bios32_end
-unknown_service:
- mov al, #0x80
-bios32_end:
-#ifdef BX_QEMU
- and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
-#endif
- popfd
- retf
-
-.align 16
-pcibios_protected:
- pushfd
- cli
- push esi
- push edi
- cmp al, #0x01 ;; installation check
- jne pci_pro_f02
- mov bx, #0x0210
- mov cx, #0
- mov edx, #0x20494350 ;; "PCI "
- mov al, #0x01
- jmp pci_pro_ok
-pci_pro_f02: ;; find pci device
- cmp al, #0x02
- jne pci_pro_f03
- shl ecx, #16
- mov cx, dx
- xor bx, bx
- mov di, #0x00
-pci_pro_devloop:
- call pci_pro_select_reg
- mov dx, #0x0cfc
- in eax, dx
- cmp eax, ecx
- jne pci_pro_nextdev
- cmp si, #0
- je pci_pro_ok
- dec si
-pci_pro_nextdev:
- inc bx
- cmp bx, #0x0100
- jne pci_pro_devloop
- mov ah, #0x86
- jmp pci_pro_fail
-pci_pro_f03: ;; find class code
- cmp al, #0x03
- jne pci_pro_f08
- xor bx, bx
- mov di, #0x08
-pci_pro_devloop2:
- call pci_pro_select_reg
- mov dx, #0x0cfc
- in eax, dx
- shr eax, #8
- cmp eax, ecx
- jne pci_pro_nextdev2
- cmp si, #0
- je pci_pro_ok
- dec si
-pci_pro_nextdev2:
- inc bx
- cmp bx, #0x0100
- jne pci_pro_devloop2
- mov ah, #0x86
- jmp pci_pro_fail
-pci_pro_f08: ;; read configuration byte
- cmp al, #0x08
- jne pci_pro_f09
- call pci_pro_select_reg
- push edx
- mov dx, di
- and dx, #0x03
- add dx, #0x0cfc
- in al, dx
- pop edx
- mov cl, al
- jmp pci_pro_ok
-pci_pro_f09: ;; read configuration word
- cmp al, #0x09
- jne pci_pro_f0a
- call pci_pro_select_reg
- push edx
- mov dx, di
- and dx, #0x02
- add dx, #0x0cfc
- in ax, dx
- pop edx
- mov cx, ax
- jmp pci_pro_ok
-pci_pro_f0a: ;; read configuration dword
- cmp al, #0x0a
- jne pci_pro_f0b
- call pci_pro_select_reg
- push edx
- mov dx, #0x0cfc
- in eax, dx
- pop edx
- mov ecx, eax
- jmp pci_pro_ok
-pci_pro_f0b: ;; write configuration byte
- cmp al, #0x0b
- jne pci_pro_f0c
- call pci_pro_select_reg
- push edx
- mov dx, di
- and dx, #0x03
- add dx, #0x0cfc
- mov al, cl
- out dx, al
- pop edx
- jmp pci_pro_ok
-pci_pro_f0c: ;; write configuration word
- cmp al, #0x0c
- jne pci_pro_f0d
- call pci_pro_select_reg
- push edx
- mov dx, di
- and dx, #0x02
- add dx, #0x0cfc
- mov ax, cx
- out dx, ax
- pop edx
- jmp pci_pro_ok
-pci_pro_f0d: ;; write configuration dword
- cmp al, #0x0d
- jne pci_pro_unknown
- call pci_pro_select_reg
- push edx
- mov dx, #0x0cfc
- mov eax, ecx
- out dx, eax
- pop edx
- jmp pci_pro_ok
-pci_pro_unknown:
- mov ah, #0x81
-pci_pro_fail:
- pop edi
- pop esi
-#ifdef BX_QEMU
- and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
-#endif
- popfd
- stc
- retf
-pci_pro_ok:
- xor ah, ah
- pop edi
- pop esi
-#ifdef BX_QEMU
- and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
-#endif
- popfd
- clc
- retf
-
-pci_pro_select_reg:
- push edx
- mov eax, #0x800000
- mov ax, bx
- shl eax, #8
- and di, #0xff
- or ax, di
- and al, #0xfc
- mov dx, #0x0cf8
- out dx, eax
- pop edx
- ret
-
-use16 386
-
-pcibios_real:
- push eax
- push dx
- mov eax, #0x80000000
- mov dx, #0x0cf8
- out dx, eax
- mov dx, #0x0cfc
- in eax, dx
-#ifdef PCI_FIXED_HOST_BRIDGE
- cmp eax, #PCI_FIXED_HOST_BRIDGE
- je pci_present
-#else
- ;; say ok if a device is present
- cmp eax, #0xffffffff
- jne pci_present
-#endif
- pop dx
- pop eax
- mov ah, #0xff
- stc
- ret
-pci_present:
- pop dx
- pop eax
- cmp al, #0x01 ;; installation check
- jne pci_real_f02
- mov ax, #0x0001
- mov bx, #0x0210
- mov cx, #0
- mov edx, #0x20494350 ;; "PCI "
- mov edi, #0xf0000
- mov di, #pcibios_protected
- clc
- ret
-pci_real_f02: ;; find pci device
- push esi
- push edi
- cmp al, #0x02
- jne pci_real_f03
- shl ecx, #16
- mov cx, dx
- xor bx, bx
- mov di, #0x00
-pci_real_devloop:
- call pci_real_select_reg
- mov dx, #0x0cfc
- in eax, dx
- cmp eax, ecx
- jne pci_real_nextdev
- cmp si, #0
- je pci_real_ok
- dec si
-pci_real_nextdev:
- inc bx
- cmp bx, #0x0100
- jne pci_real_devloop
- mov dx, cx
- shr ecx, #16
- mov ax, #0x8602
- jmp pci_real_fail
-pci_real_f03: ;; find class code
- cmp al, #0x03
- jne pci_real_f08
- xor bx, bx
- mov di, #0x08
-pci_real_devloop2:
- call pci_real_select_reg
- mov dx, #0x0cfc
- in eax, dx
- shr eax, #8
- cmp eax, ecx
- jne pci_real_nextdev2
- cmp si, #0
- je pci_real_ok
- dec si
-pci_real_nextdev2:
- inc bx
- cmp bx, #0x0100
- jne pci_real_devloop2
- mov dx, cx
- shr ecx, #16
- mov ax, #0x8603
- jmp pci_real_fail
-pci_real_f08: ;; read configuration byte
- cmp al, #0x08
- jne pci_real_f09
- call pci_real_select_reg
- push dx
- mov dx, di
- and dx, #0x03
- add dx, #0x0cfc
- in al, dx
- pop dx
- mov cl, al
- jmp pci_real_ok
-pci_real_f09: ;; read configuration word
- cmp al, #0x09
- jne pci_real_f0a
- call pci_real_select_reg
- push dx
- mov dx, di
- and dx, #0x02
- add dx, #0x0cfc
- in ax, dx
- pop dx
- mov cx, ax
- jmp pci_real_ok
-pci_real_f0a: ;; read configuration dword
- cmp al, #0x0a
- jne pci_real_f0b
- call pci_real_select_reg
- push dx
- mov dx, #0x0cfc
- in eax, dx
- pop dx
- mov ecx, eax
- jmp pci_real_ok
-pci_real_f0b: ;; write configuration byte
- cmp al, #0x0b
- jne pci_real_f0c
- call pci_real_select_reg
- push dx
- mov dx, di
- and dx, #0x03
- add dx, #0x0cfc
- mov al, cl
- out dx, al
- pop dx
- jmp pci_real_ok
-pci_real_f0c: ;; write configuration word
- cmp al, #0x0c
- jne pci_real_f0d
- call pci_real_select_reg
- push dx
- mov dx, di
- and dx, #0x02
- add dx, #0x0cfc
- mov ax, cx
- out dx, ax
- pop dx
- jmp pci_real_ok
-pci_real_f0d: ;; write configuration dword
- cmp al, #0x0d
- jne pci_real_f0e
- call pci_real_select_reg
- push dx
- mov dx, #0x0cfc
- mov eax, ecx
- out dx, eax
- pop dx
- jmp pci_real_ok
-pci_real_f0e: ;; get irq routing options
- cmp al, #0x0e
- jne pci_real_unknown
- SEG ES
- cmp word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
- jb pci_real_too_small
- SEG ES
- mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
- pushf
- push ds
- push es
- push cx
- push si
- push di
- cld
- mov si, #pci_routing_table_structure_start
- push cs
- pop ds
- SEG ES
- mov cx, [di+2]
- SEG ES
- mov es, [di+4]
- mov di, cx
- mov cx, #pci_routing_table_structure_end - pci_routing_table_structure_start
- rep
- movsb
- pop di
- pop si
- pop cx
- pop es
- pop ds
- popf
- mov bx, #(1 << 9) | (1 << 11) ;; irq 9 and 11 are used
- jmp pci_real_ok
-pci_real_too_small:
- SEG ES
- mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
- mov ah, #0x89
- jmp pci_real_fail
-
-pci_real_unknown:
- mov ah, #0x81
-pci_real_fail:
- pop edi
- pop esi
- stc
- ret
-pci_real_ok:
- xor ah, ah
- pop edi
- pop esi
- clc
- ret
-
-pci_real_select_reg:
- push dx
- mov eax, #0x800000
- mov ax, bx
- shl eax, #8
- and di, #0xff
- or ax, di
- and al, #0xfc
- mov dx, #0x0cf8
- out dx, eax
- pop dx
- ret
-
-.align 16
-pci_routing_table_structure:
- db 0x24, 0x50, 0x49, 0x52 ;; "$PIR" signature
- db 0, 1 ;; version
- dw 32 + (6 * 16) ;; table size
- db 0 ;; PCI interrupt router bus
- db 0x08 ;; PCI interrupt router DevFunc
- dw 0x0000 ;; PCI exclusive IRQs
- dw 0x8086 ;; compatible PCI interrupt router vendor ID
- dw 0x122e ;; compatible PCI interrupt router device ID
- dw 0,0 ;; Miniport data
- db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
- db 0x37 ;; checksum
-pci_routing_table_structure_start:
- ;; first slot entry PCI-to-ISA (embedded)
- db 0 ;; pci bus number
- db 0x08 ;; pci device number (bit 7-3)
- db 0x60 ;; link value INTA#: pointer into PCI2ISA config space
- dw 0xdef8 ;; IRQ bitmap INTA#
- db 0x61 ;; link value INTB#
- dw 0xdef8 ;; IRQ bitmap INTB#
- db 0x62 ;; link value INTC#
- dw 0xdef8 ;; IRQ bitmap INTC#
- db 0x63 ;; link value INTD#
- dw 0xdef8 ;; IRQ bitmap INTD#
- db 0 ;; physical slot (0 = embedded)
- db 0 ;; reserved
- ;; second slot entry: 1st PCI slot
- db 0 ;; pci bus number
- db 0x10 ;; pci device number (bit 7-3)
- db 0x61 ;; link value INTA#
- dw 0xdef8 ;; IRQ bitmap INTA#
- db 0x62 ;; link value INTB#
- dw 0xdef8 ;; IRQ bitmap INTB#
- db 0x63 ;; link value INTC#
- dw 0xdef8 ;; IRQ bitmap INTC#
- db 0x60 ;; link value INTD#
- dw 0xdef8 ;; IRQ bitmap INTD#
- db 1 ;; physical slot (0 = embedded)
- db 0 ;; reserved
- ;; third slot entry: 2nd PCI slot
- db 0 ;; pci bus number
- db 0x18 ;; pci device number (bit 7-3)
- db 0x62 ;; link value INTA#
- dw 0xdef8 ;; IRQ bitmap INTA#
- db 0x63 ;; link value INTB#
- dw 0xdef8 ;; IRQ bitmap INTB#
- db 0x60 ;; link value INTC#
- dw 0xdef8 ;; IRQ bitmap INTC#
- db 0x61 ;; link value INTD#
- dw 0xdef8 ;; IRQ bitmap INTD#
- db 2 ;; physical slot (0 = embedded)
- db 0 ;; reserved
- ;; 4th slot entry: 3rd PCI slot
- db 0 ;; pci bus number
- db 0x20 ;; pci device number (bit 7-3)
- db 0x63 ;; link value INTA#
- dw 0xdef8 ;; IRQ bitmap INTA#
- db 0x60 ;; link value INTB#
- dw 0xdef8 ;; IRQ bitmap INTB#
- db 0x61 ;; link value INTC#
- dw 0xdef8 ;; IRQ bitmap INTC#
- db 0x62 ;; link value INTD#
- dw 0xdef8 ;; IRQ bitmap INTD#
- db 3 ;; physical slot (0 = embedded)
- db 0 ;; reserved
- ;; 5th slot entry: 4rd PCI slot
- db 0 ;; pci bus number
- db 0x28 ;; pci device number (bit 7-3)
- db 0x60 ;; link value INTA#
- dw 0xdef8 ;; IRQ bitmap INTA#
- db 0x61 ;; link value INTB#
- dw 0xdef8 ;; IRQ bitmap INTB#
- db 0x62 ;; link value INTC#
- dw 0xdef8 ;; IRQ bitmap INTC#
- db 0x63 ;; link value INTD#
- dw 0xdef8 ;; IRQ bitmap INTD#
- db 4 ;; physical slot (0 = embedded)
- db 0 ;; reserved
- ;; 6th slot entry: 5rd PCI slot
- db 0 ;; pci bus number
- db 0x30 ;; pci device number (bit 7-3)
- db 0x61 ;; link value INTA#
- dw 0xdef8 ;; IRQ bitmap INTA#
- db 0x62 ;; link value INTB#
- dw 0xdef8 ;; IRQ bitmap INTB#
- db 0x63 ;; link value INTC#
- dw 0xdef8 ;; IRQ bitmap INTC#
- db 0x60 ;; link value INTD#
- dw 0xdef8 ;; IRQ bitmap INTD#
- db 5 ;; physical slot (0 = embedded)
- db 0 ;; reserved
-pci_routing_table_structure_end:
-
-#if !BX_ROMBIOS32
-pci_irq_list:
- db 11, 10, 9, 5;
-
-pcibios_init_sel_reg:
- push eax
- mov eax, #0x800000
- mov ax, bx
- shl eax, #8
- and dl, #0xfc
- or al, dl
- mov dx, #0x0cf8
- out dx, eax
- pop eax
- ret
-
-pcibios_init_iomem_bases:
- push bp
- mov bp, sp
- mov eax, #0xe0000000 ;; base for memory init
- push eax
- mov ax, #0xc000 ;; base for i/o init
- push ax
- mov ax, #0x0010 ;; start at base address #0
- push ax
- mov bx, #0x0008
-pci_init_io_loop1:
- mov dl, #0x00
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- in ax, dx
- cmp ax, #0xffff
- jz next_pci_dev
- mov dl, #0x04 ;; disable i/o and memory space access
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- in al, dx
- and al, #0xfc
- out dx, al
-pci_init_io_loop2:
- mov dl, [bp-8]
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- in eax, dx
- test al, #0x01
- jnz init_io_base
- mov ecx, eax
- mov eax, #0xffffffff
- out dx, eax
- in eax, dx
- cmp eax, ecx
- je next_pci_base
- xor eax, #0xffffffff
- mov ecx, eax
- mov eax, [bp-4]
- out dx, eax
- add eax, ecx ;; calculate next free mem base
- add eax, #0x01000000
- and eax, #0xff000000
- mov [bp-4], eax
- jmp next_pci_base
-init_io_base:
- mov cx, ax
- mov ax, #0xffff
- out dx, ax
- in ax, dx
- cmp ax, cx
- je next_pci_base
- xor ax, #0xfffe
- mov cx, ax
- mov ax, [bp-6]
- out dx, ax
- add ax, cx ;; calculate next free i/o base
- add ax, #0x0100
- and ax, #0xff00
- mov [bp-6], ax
-next_pci_base:
- mov al, [bp-8]
- add al, #0x04
- cmp al, #0x28
- je enable_iomem_space
- mov byte ptr[bp-8], al
- jmp pci_init_io_loop2
-enable_iomem_space:
- mov dl, #0x04 ;; enable i/o and memory space access if available
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- in al, dx
- or al, #0x07
- out dx, al
-next_pci_dev:
- mov byte ptr[bp-8], #0x10
- inc bx
- cmp bx, #0x0100
- jne pci_init_io_loop1
- mov sp, bp
- pop bp
- ret
-
-pcibios_init_set_elcr:
- push ax
- push cx
- mov dx, #0x04d0
- test al, #0x08
- jz is_master_pic
- inc dx
- and al, #0x07
-is_master_pic:
- mov cl, al
- mov bl, #0x01
- shl bl, cl
- in al, dx
- or al, bl
- out dx, al
- pop cx
- pop ax
- ret
-
-pcibios_init_irqs:
- push ds
- push bp
- mov ax, #0xf000
- mov ds, ax
- mov dx, #0x04d0 ;; reset ELCR1 + ELCR2
- mov al, #0x00
- out dx, al
- inc dx
- out dx, al
- mov si, #pci_routing_table_structure
- mov bh, [si+8]
- mov bl, [si+9]
- mov dl, #0x00
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- in ax, dx
- cmp ax, [si+12] ;; check irq router
- jne pci_init_end
- mov dl, [si+34]
- call pcibios_init_sel_reg
- push bx ;; save irq router bus + devfunc
- mov dx, #0x0cfc
- mov ax, #0x8080
- out dx, ax ;; reset PIRQ route control
- add dx, #2
- out dx, ax
- mov ax, [si+6]
- sub ax, #0x20
- shr ax, #4
- mov cx, ax
- add si, #0x20 ;; set pointer to 1st entry
- mov bp, sp
- mov ax, #pci_irq_list
- push ax
- xor ax, ax
- push ax
-pci_init_irq_loop1:
- mov bh, [si]
- mov bl, [si+1]
-pci_init_irq_loop2:
- mov dl, #0x00
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- in ax, dx
- cmp ax, #0xffff
- jnz pci_test_int_pin
- test bl, #0x07
- jz next_pir_entry
- jmp next_pci_func
-pci_test_int_pin:
- mov dl, #0x3c
- call pcibios_init_sel_reg
- mov dx, #0x0cfd
- in al, dx
- and al, #0x07
- jz next_pci_func
- dec al ;; determine pirq reg
- mov dl, #0x03
- mul al, dl
- add al, #0x02
- xor ah, ah
- mov bx, ax
- mov al, [si+bx]
- mov dl, al
- mov bx, [bp]
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- and al, #0x03
- add dl, al
- in al, dx
- cmp al, #0x80
- jb pirq_found
- mov bx, [bp-2] ;; pci irq list pointer
- mov al, [bx]
- out dx, al
- inc bx
- mov [bp-2], bx
- call pcibios_init_set_elcr
-pirq_found:
- mov bh, [si]
- mov bl, [si+1]
- add bl, [bp-3] ;; pci function number
- mov dl, #0x3c
- call pcibios_init_sel_reg
- mov dx, #0x0cfc
- out dx, al
-next_pci_func:
- inc byte ptr[bp-3]
- inc bl
- test bl, #0x07
- jnz pci_init_irq_loop2
-next_pir_entry:
- add si, #0x10
- mov byte ptr[bp-3], #0x00
- loop pci_init_irq_loop1
- mov sp, bp
- pop bx
-pci_init_end:
- pop bp
- pop ds
- ret
-#endif // !BX_ROMBIOS32
-#endif // BX_PCIBIOS
-
-#if BX_ROMBIOS32
-rombios32_init:
- ;; save a20 and enable it
- in al, 0x92
- push ax
- or al, #0x02
- out 0x92, al
-
- ;; save SS:SP to the BDA
- xor ax, ax
- mov ds, ax
- mov 0x0469, ss
- mov 0x0467, sp
-
- SEG CS
- lidt [pmode_IDT_info]
- SEG CS
- lgdt [rombios32_gdt_48]
- ;; set PE bit in CR0
- mov eax, cr0
- or al, #0x01
- mov cr0, eax
- ;; start protected mode code: ljmpl 0x10:rombios32_init1
- db 0x66, 0xea
- dw rombios32_05
- dw 0x000f ;; high 16 bit address
- dw 0x0010
-
-use32 386
-rombios32_05:
- ;; init data segments
- mov eax, #0x18
- mov ds, ax
- mov es, ax
- mov ss, ax
- xor eax, eax
- mov fs, ax
- mov gs, ax
- cld
-
- ;; init the stack pointer to point below EBDA
- mov ax, [0x040e]
- shl eax, #4
- mov esp, #-0x10
- add esp, eax
-
- ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32
- push #0x04b0
- push #0x04b2
-
- ;; call rombios32 code
- mov eax, #0x000e0000
- call eax
-
- ;; return to 16 bit protected mode first
- db 0xea
- dd rombios32_10
- dw 0x20
-
-use16 386
-rombios32_10:
- ;; restore data segment limits to 0xffff
- mov ax, #0x28
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov fs, ax
- mov gs, ax
-
- ;; reset PE bit in CR0
- mov eax, cr0
- and al, #0xFE
- mov cr0, eax
-
- ;; far jump to flush CPU queue after transition to real mode
- JMP_AP(0xf000, rombios32_real_mode)
-
-rombios32_real_mode:
- ;; restore IDT to normal real-mode defaults
- SEG CS
- lidt [rmode_IDT_info]
-
- xor ax, ax
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- ;; restore SS:SP from the BDA
- mov ss, 0x0469
- xor esp, esp
- mov sp, 0x0467
- ;; restore a20
- pop ax
- out 0x92, al
- ret
-
-rombios32_gdt_48:
- dw 0x30
- dw rombios32_gdt
- dw 0x000f
-
-rombios32_gdt:
- dw 0, 0, 0, 0
- dw 0, 0, 0, 0
- dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10)
- dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18)
- dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff
- dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff
-#endif // BX_ROMBIOS32
-
-
-; parallel port detection: base address in DX, index in BX, timeout in CL
-detect_parport:
- push dx
- add dx, #2
- in al, dx
- and al, #0xdf ; clear input mode
- out dx, al
- pop dx
- mov al, #0xaa
- out dx, al
- in al, dx
- cmp al, #0xaa
- jne no_parport
- push bx
- shl bx, #1
- mov [bx+0x408], dx ; Parallel I/O address
- pop bx
- mov [bx+0x478], cl ; Parallel printer timeout
- inc bx
-no_parport:
- ret
-
-; serial port detection: base address in DX, index in BX, timeout in CL
-detect_serial:
- push dx
- inc dx
- mov al, #0x02
- out dx, al
- in al, dx
- cmp al, #0x02
- jne no_serial
- inc dx
- in al, dx
- cmp al, #0x02
- jne no_serial
- dec dx
- xor al, al
- out dx, al
- pop dx
- push bx
- shl bx, #1
- mov [bx+0x400], dx ; Serial I/O address
- pop bx
- mov [bx+0x47c], cl ; Serial timeout
- inc bx
- ret
-no_serial:
- pop dx
- ret
-
-rom_checksum:
- push ax
- push bx
- push cx
- xor ax, ax
- xor bx, bx
- xor cx, cx
- mov ch, [2]
- shl cx, #1
-checksum_loop:
- add al, [bx]
- inc bx
- loop checksum_loop
- and al, #0xff
- pop cx
- pop bx
- pop ax
- ret
-
-
-;; We need a copy of this string, but we are not actually a PnP BIOS,
-;; so make sure it is *not* aligned, so OSes will not see it if they scan.
-.align 16
- db 0
-pnp_string:
- .ascii "$PnP"
-
-
-rom_scan:
- ;; Scan for existence of valid expansion ROMS.
- ;; Video ROM: from 0xC0000..0xC7FFF in 2k increments
- ;; General ROM: from 0xC8000..0xDFFFF in 2k increments
- ;; System ROM: only 0xE0000
- ;;
- ;; Header:
- ;; Offset Value
- ;; 0 0x55
- ;; 1 0xAA
- ;; 2 ROM length in 512-byte blocks
- ;; 3 ROM initialization entry point (FAR CALL)
-
-rom_scan_loop:
- push ax ;; Save AX
- mov ds, cx
- mov ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k
- cmp [0], #0xAA55 ;; look for signature
- jne rom_scan_increment
- call rom_checksum
- jnz rom_scan_increment
- mov al, [2] ;; change increment to ROM length in 512-byte blocks
-
- ;; We want our increment in 512-byte quantities, rounded to
- ;; the nearest 2k quantity, since we only scan at 2k intervals.
- test al, #0x03
- jz block_count_rounded
- and al, #0xfc ;; needs rounding up
- add al, #0x04
-block_count_rounded:
-
- push ax ;; Save AX
- push di ;; Save DI
- ;; Push addr of ROM entry point
- push cx ;; Push seg
- push #0x0003 ;; Push offset
-
- ;; Get the BDF into ax before invoking the option ROM
- mov bl, [2]
- mov al, bl
- shr al, #7
- cmp al, #1
- jne fetch_bdf
- mov ax, ds ;; Increment the DS since rom size larger than an segment
- add ax, #0x1000
- mov ds, ax
-fetch_bdf:
- shl bx, #9
- xor ax, ax
- mov al, [bx]
-
- ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
- ;; That should stop it grabbing INT 19h; we will use its BEV instead.
- mov bx, #0xf000
- mov es, bx
- lea di, pnp_string
-
- mov bp, sp ;; Call ROM init routine using seg:off on stack
- db 0xff ;; call_far ss:[bp+0]
- db 0x5e
- db 0
- cli ;; In case expansion ROM BIOS turns IF on
- add sp, #2 ;; Pop offset value
- pop cx ;; Pop seg value (restore CX)
-
- ;; Look at the ROM's PnP Expansion header. Properly, we're supposed
- ;; to init all the ROMs and then go back and build an IPL table of
- ;; all the bootable devices, but we can get away with one pass.
- mov ds, cx ;; ROM base
- mov bx, 0x001a ;; 0x1A is the offset into ROM header that contains...
- mov ax, [bx] ;; the offset of PnP expansion header, where...
- cmp ax, #0x5024 ;; we look for signature "$PnP"
- jne no_bev
- mov ax, 2[bx]
- cmp ax, #0x506e
- jne no_bev
-
- mov ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector
- cmp ax, #0x0000
- je no_bcv
-
- ;; Option ROM has BCV. Run it now.
- push cx ;; Push seg
- push ax ;; Push offset
-
- ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
- mov bx, #0xf000
- mov es, bx
- lea di, pnp_string
- /* jump to BCV function entry pointer */
- mov bp, sp ;; Call ROM BCV routine using seg:off on stack
- db 0xff ;; call_far ss:[bp+0]
- db 0x5e
- db 0
- cli ;; In case expansion ROM BIOS turns IF on
- add sp, #2 ;; Pop offset value
- pop cx ;; Pop seg value (restore CX)
- jmp no_bev
-
-no_bcv:
- mov ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
- cmp ax, #0x0000 ;; the Bootstrap Entry Vector, or zero if there is none.
- je no_bev
-
- ;; Found a device that thinks it can boot the system. Record its BEV and product name string.
- mov di, 0x10[bx] ;; Pointer to the product name string or zero if none
- mov bx, #IPL_SEG ;; Go to the segment where the IPL table lives
- mov ds, bx
- mov bx, IPL_COUNT_OFFSET ;; Read the number of entries so far
- cmp bx, #IPL_TABLE_ENTRIES
- je no_bev ;; Get out if the table is full
- shl bx, #0x4 ;; Turn count into offset (entries are 16 bytes)
- mov 0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device
- mov 6[bx], cx ;; Build a far pointer from the segment...
- mov 4[bx], ax ;; and the offset
- cmp di, #0x0000
- je no_prod_str
- mov 0xA[bx], cx ;; Build a far pointer from the segment...
- mov 8[bx], di ;; and the offset
-no_prod_str:
- shr bx, #0x4 ;; Turn the offset back into a count
- inc bx ;; We have one more entry now
- mov IPL_COUNT_OFFSET, bx ;; Remember that.
-
-no_bev:
- pop di ;; Restore DI
- pop ax ;; Restore AX
-rom_scan_increment:
- shl ax, #5 ;; convert 512-bytes blocks to 16-byte increments
- ;; because the segment selector is shifted left 4 bits.
- add cx, ax
- pop ax ;; Restore AX
- cmp cx, ax
- jbe rom_scan_loop
-
- xor ax, ax ;; Restore DS back to 0000:
- mov ds, ax
- ret
-
-post_enable_cache:
- ;; enable cache
- mov eax, cr0
- and eax, #0x9fffffff
- mov cr0, eax
- jmp post_enable_cache_done
-
-post_init_pic:
- mov al, #0x11 ; send initialisation commands
- out 0x20, al
- out 0xa0, al
- mov al, #0x08
- out 0x21, al
- mov al, #0x70
- out 0xa1, al
- mov al, #0x04
- out 0x21, al
- mov al, #0x02
- out 0xa1, al
- mov al, #0x01
- out 0x21, al
- out 0xa1, al
- mov al, #0xb8
- out 0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
-#if BX_USE_PS2_MOUSE
- mov al, #0x8f
-#else
- mov al, #0x9f
-#endif
- out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
- ret
-
-;; the following area can be used to write dynamically generated tables
- .align 16
-bios_table_area_start:
- dd 0xaafb4442
- dd bios_table_area_end - bios_table_area_start - 8;
-
-
-;--------
-;- POST -
-;--------
-.org 0xe05b ; POST Entry Point
-post:
- jmp post_enable_cache ; hack: we have limited space before next .org,
- ; so take this bit out-of-line
-post_enable_cache_done:
- xor ax, ax
-
- ;; first reset the DMA controllers
- out 0x0d,al
- out 0xda,al
-
- ;; then initialize the DMA controllers
- mov al, #0xC0
- out 0xD6, al ; cascade mode of channel 4 enabled
- mov al, #0x00
- out 0xD4, al ; unmask channel 4
-
- ;; Examine CMOS shutdown status.
- mov AL, #0x0f
- out 0x70, AL
- in AL, 0x71
-
- ;; backup status
- mov bl, al
-
- ;; Reset CMOS shutdown status.
- mov AL, #0x0f
- out 0x70, AL ; select CMOS register Fh
- mov AL, #0x00
- out 0x71, AL ; set shutdown action to normal
-
- ;; Examine CMOS shutdown status.
- mov al, bl
-
- ;; 0x00, 0x09, 0x0D+ = normal startup
- cmp AL, #0x00
- jz normal_post
- cmp AL, #0x0d
- jae normal_post
- cmp AL, #0x09
- je normal_post
-
- ;; 0x05 = eoi + jmp via [0x40:0x67] jump
- cmp al, #0x05
- je eoi_jmp_post
-
- ;; 0x0A = jmp via [0x40:0x67] jump
- cmp al, #0x0a
- je jmp_post_0x467
-
- ;; 0x0B = iret via [0x40:0x67]
- cmp al, #0x0b
- je iret_post_0x467
-
- ;; 0x0C = retf via [0x40:0x67]
- cmp al, #0x0c
- je retf_post_0x467
-
- ;; Examine CMOS shutdown status.
- ;; 0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status.
- push bx
- call _shutdown_status_panic
-
-#if 0
- HALT(__LINE__)
- ;
- ;#if 0
- ; 0xb0, 0x20, /* mov al, #0x20 */
- ; 0xe6, 0x20, /* out 0x20, al ;send EOI to PIC */
- ;#endif
- ;
- pop es
- pop ds
- popa
- iret
-#endif
-
-normal_post:
- ; case 0: normal startup
-
- cli
- mov ax, #0xfffe
- mov sp, ax
- xor ax, ax
- mov ds, ax
- mov ss, ax
-
- ;; Save shutdown status
- mov 0x04b0, bl
-
- cmp bl, #0xfe
- jz s3_post
-
- ;; zero out BIOS data area (40:00..40:ff)
- mov es, ax
- mov cx, #0x0080 ;; 128 words
- mov di, #0x0400
- cld
- rep
- stosw
-
- call _log_bios_start
-
- ;; set all interrupts to default handler
- xor bx, bx ;; offset index
- mov cx, #0x0100 ;; counter (256 interrupts)
- mov ax, #dummy_iret_handler
- mov dx, #0xF000
-
-post_default_ints:
- mov [bx], ax
- add bx, #2
- mov [bx], dx
- add bx, #2
- loop post_default_ints
-
- ;; set vector 0x79 to zero
- ;; this is used by 'gardian angel' protection system
- SET_INT_VECTOR(0x79, #0, #0)
-
- ;; base memory in K 40:13 (word)
- mov ax, #BASE_MEM_IN_K
- mov 0x0413, ax
-
-
- ;; Manufacturing Test 40:12
- ;; zerod out above
-
- ;; Warm Boot Flag 0040:0072
- ;; value of 1234h = skip memory checks
- ;; zerod out above
-
-
- ;; Printer Services vector
- SET_INT_VECTOR(0x17, #0xF000, #int17_handler)
-
- ;; Bootstrap failure vector
- SET_INT_VECTOR(0x18, #0xF000, #int18_handler)
-
- ;; Bootstrap Loader vector
- SET_INT_VECTOR(0x19, #0xF000, #int19_handler)
-
- ;; User Timer Tick vector
- SET_INT_VECTOR(0x1c, #0xF000, #int1c_handler)
-
- ;; Memory Size Check vector
- SET_INT_VECTOR(0x12, #0xF000, #int12_handler)
-
- ;; Equipment Configuration Check vector
- SET_INT_VECTOR(0x11, #0xF000, #int11_handler)
-
- ;; System Services
- SET_INT_VECTOR(0x15, #0xF000, #int15_handler)
-
- ;; EBDA setup
- call ebda_post
-
- ;; PIT setup
- SET_INT_VECTOR(0x08, #0xF000, #int08_handler)
- ;; int 1C already points at dummy_iret_handler (above)
- mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
- out 0x43, al
- mov al, #0x00 ; maximum count of 0000H = 18.2Hz
- out 0x40, al
- out 0x40, al
-
- ;; Keyboard
- SET_INT_VECTOR(0x09, #0xF000, #int09_handler)
- SET_INT_VECTOR(0x16, #0xF000, #int16_handler)
-
- xor ax, ax
- mov ds, ax
- mov 0x0417, al /* keyboard shift flags, set 1 */
- mov 0x0418, al /* keyboard shift flags, set 2 */
- mov 0x0419, al /* keyboard alt-numpad work area */
- mov 0x0471, al /* keyboard ctrl-break flag */
- mov 0x0497, al /* keyboard status flags 4 */
- mov al, #0x10
- mov 0x0496, al /* keyboard status flags 3 */
-
-
- /* keyboard head of buffer pointer */
- mov bx, #0x001E
- mov 0x041A, bx
-
- /* keyboard end of buffer pointer */
- mov 0x041C, bx
-
- /* keyboard pointer to start of buffer */
- mov bx, #0x001E
- mov 0x0480, bx
-
- /* keyboard pointer to end of buffer */
- mov bx, #0x003E
- mov 0x0482, bx
-
- /* init the keyboard */
- call _keyboard_init
-
- ;; mov CMOS Equipment Byte to BDA Equipment Word
- mov ax, 0x0410
- mov al, #0x14
- out 0x70, al
- in al, 0x71
- mov 0x0410, ax
-
-
- ;; Parallel setup
- SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler)
- xor ax, ax
- mov ds, ax
- xor bx, bx
- mov cl, #0x14 ; timeout value
- mov dx, #0x378 ; Parallel I/O address, port 1
- call detect_parport
- mov dx, #0x278 ; Parallel I/O address, port 2
- call detect_parport
- shl bx, #0x0e
- mov ax, 0x410 ; Equipment word bits 14..15 determing # parallel ports
- and ax, #0x3fff
- or ax, bx ; set number of parallel ports
- mov 0x410, ax
-
- ;; Serial setup
- SET_INT_VECTOR(0x0C, #0xF000, #dummy_iret_handler)
- SET_INT_VECTOR(0x14, #0xF000, #int14_handler)
- xor bx, bx
- mov cl, #0x0a ; timeout value
- mov dx, #0x03f8 ; Serial I/O address, port 1
- call detect_serial
- mov dx, #0x02f8 ; Serial I/O address, port 2
- call detect_serial
- mov dx, #0x03e8 ; Serial I/O address, port 3
- call detect_serial
- mov dx, #0x02e8 ; Serial I/O address, port 4
- call detect_serial
- shl bx, #0x09
- mov ax, 0x410 ; Equipment word bits 9..11 determing # serial ports
- and ax, #0xf1ff
- or ax, bx ; set number of serial port
- mov 0x410, ax
-
- ;; CMOS RTC
- SET_INT_VECTOR(0x1A, #0xF000, #int1a_handler)
- SET_INT_VECTOR(0x4A, #0xF000, #dummy_iret_handler)
- SET_INT_VECTOR(0x70, #0xF000, #int70_handler)
- ;; BIOS DATA AREA 0x4CE ???
- call timer_tick_post
-
- ;; PS/2 mouse setup
- SET_INT_VECTOR(0x74, #0xF000, #int74_handler)
-
- ;; IRQ13 (FPU exception) setup
- SET_INT_VECTOR(0x75, #0xF000, #int75_handler)
-
- ;; Video setup
- SET_INT_VECTOR(0x10, #0xF000, #int10_handler)
-
- ;; PIC
- call post_init_pic
-
- mov cx, #0xc000 ;; init vga bios
- mov ax, #0xc780
- call rom_scan
-
- call _print_bios_banner
-
-#if BX_ROMBIOS32
- call rombios32_init
-#else
-#if BX_PCIBIOS
- call pcibios_init_iomem_bases
- call pcibios_init_irqs
-#endif //BX_PCIBIOS
-#endif
-
- ;;
- ;; Floppy setup
- ;;
- call floppy_drive_post
-
- ;;
- ;; Hard Drive setup
- ;;
- call hard_drive_post
-
-#if BX_USE_ATADRV
-
- ;;
- ;; ATA/ATAPI driver setup
- ;;
- call _ata_init
- call _ata_detect
- ;;
-
-#endif // BX_USE_ATADRV
-
-#if BX_ELTORITO_BOOT
- ;;
- ;; eltorito floppy/harddisk emulation from cd
- ;;
- call _cdemu_init
- ;;
-#endif // BX_ELTORITO_BOOT
-
- call _init_boot_vectors
-
- mov cx, #0xc800 ;; init option roms
- mov ax, #0xe000
- call rom_scan
-
-#if BX_ELTORITO_BOOT
- call _interactive_bootkey
-#endif // BX_ELTORITO_BOOT
-
- sti ;; enable interrupts
- int #0x19
-
-.org 0xe2c3 ; NMI Handler Entry Point
-nmi:
- ;; FIXME the NMI handler should not panic
- ;; but iret when called from int75 (fpu exception)
- call _nmi_handler_msg
- iret
-
-int75_handler:
- out 0xf0, al // clear irq13
- call eoi_both_pics // clear interrupt
- int 2 // legacy nmi call
- iret
-
-;-------------------------------------------
-;- INT 13h Fixed Disk Services Entry Point -
-;-------------------------------------------
-.org 0xe3fe ; INT 13h Fixed Disk Services Entry Point
-int13_handler:
- //JMPL(int13_relocated)
- jmp int13_relocated
-
-.org 0xe401 ; Fixed Disk Parameter Table
-
-;----------
-;- INT19h -
-;----------
-.org 0xe6f2 ; INT 19h Boot Load Service Entry Point
-int19_handler:
-
- jmp int19_relocated
-;-------------------------------------------
-;- System BIOS Configuration Data Table
-;-------------------------------------------
-.org BIOS_CONFIG_TABLE
-db 0x08 ; Table size (bytes) -Lo
-db 0x00 ; Table size (bytes) -Hi
-db SYS_MODEL_ID
-db SYS_SUBMODEL_ID
-db BIOS_REVISION
-; Feature byte 1
-; b7: 1=DMA channel 3 used by hard disk
-; b6: 1=2 interrupt controllers present
-; b5: 1=RTC present
-; b4: 1=BIOS calls int 15h/4Fh every key
-; b3: 1=wait for extern event supported (Int 15h/41h)
-; b2: 1=extended BIOS data area used
-; b1: 0=AT or ESDI bus, 1=MicroChannel
-; b0: 1=Dual bus (MicroChannel + ISA)
-db (0 << 7) | \
- (1 << 6) | \
- (1 << 5) | \
- (BX_CALL_INT15_4F << 4) | \
- (0 << 3) | \
- (BX_USE_EBDA << 2) | \
- (0 << 1) | \
- (0 << 0)
-; Feature byte 2
-; b7: 1=32-bit DMA supported
-; b6: 1=int16h, function 9 supported
-; b5: 1=int15h/C6h (get POS data) supported
-; b4: 1=int15h/C7h (get mem map info) supported
-; b3: 1=int15h/C8h (en/dis CPU) supported
-; b2: 1=non-8042 kb controller
-; b1: 1=data streaming supported
-; b0: reserved
-db (0 << 7) | \
- (1 << 6) | \
- (0 << 5) | \
- (0 << 4) | \
- (0 << 3) | \
- (0 << 2) | \
- (0 << 1) | \
- (0 << 0)
-; Feature byte 3
-; b7: not used
-; b6: reserved
-; b5: reserved
-; b4: POST supports ROM-to-RAM enable/disable
-; b3: SCSI on system board
-; b2: info panel installed
-; b1: Initial Machine Load (IML) system - BIOS on disk
-; b0: SCSI supported in IML
-db 0x00
-; Feature byte 4
-; b7: IBM private
-; b6: EEPROM present
-; b5-3: ABIOS presence (011 = not supported)
-; b2: private
-; b1: memory split above 16Mb supported
-; b0: POSTEXT directly supported by POST
-db 0x00
-; Feature byte 5 (IBM)
-; b1: enhanced mouse
-; b0: flash EPROM
-db 0x00
-
-
-
-.org 0xe729 ; Baud Rate Generator Table
-
-;----------
-;- INT14h -
-;----------
-.org 0xe739 ; INT 14h Serial Communications Service Entry Point
-int14_handler:
- push ds
- pusha
- xor ax, ax
- mov ds, ax
- call _int14_function
- popa
- pop ds
- iret
-
-
-;----------------------------------------
-;- INT 16h Keyboard Service Entry Point -
-;----------------------------------------
-.org 0xe82e
-int16_handler:
-
- sti
- push ds
- pushf
- pusha
-
- cmp ah, #0x00
- je int16_F00
- cmp ah, #0x10
- je int16_F00
-
- mov bx, #0xf000
- mov ds, bx
- call _int16_function
- popa
- popf
- pop ds
- jz int16_zero_set
-
-int16_zero_clear:
- push bp
- mov bp, sp
- //SEG SS
- and BYTE [bp + 0x06], #0xbf
- pop bp
- iret
-
-int16_zero_set:
- push bp
- mov bp, sp
- //SEG SS
- or BYTE [bp + 0x06], #0x40
- pop bp
- iret
-
-int16_F00:
- mov bx, #0x0040
- mov ds, bx
-
-int16_wait_for_key:
- cli
- mov bx, 0x001a
- cmp bx, 0x001c
- jne int16_key_found
- sti
- nop
-#if 0
- /* no key yet, call int 15h, function AX=9002 */
- 0x50, /* push AX */
- 0xb8, 0x02, 0x90, /* mov AX, #0x9002 */
- 0xcd, 0x15, /* int 15h */
- 0x58, /* pop AX */
- 0xeb, 0xea, /* jmp WAIT_FOR_KEY */
-#endif
- jmp int16_wait_for_key
-
-int16_key_found:
- mov bx, #0xf000
- mov ds, bx
- call _int16_function
- popa
- popf
- pop ds
-#if 0
- /* notify int16 complete w/ int 15h, function AX=9102 */
- 0x50, /* push AX */
- 0xb8, 0x02, 0x91, /* mov AX, #0x9102 */
- 0xcd, 0x15, /* int 15h */
- 0x58, /* pop AX */
-#endif
- iret
-
-
-
-;-------------------------------------------------
-;- INT09h : Keyboard Hardware Service Entry Point -
-;-------------------------------------------------
-.org 0xe987
-int09_handler:
- cli
- push ax
-
- mov al, #0xAD ;;disable keyboard
- out #0x64, al
-
- mov al, #0x0B
- out #0x20, al
- in al, #0x20
- and al, #0x02
- jz int09_finish
-
- in al, #0x60 ;;read key from keyboard controller
- sti
- push ds
- pusha
-#ifdef BX_CALL_INT15_4F
- mov ah, #0x4f ;; allow for keyboard intercept
- stc
- int #0x15
- jnc int09_done
-#endif
-
- ;; check for extended key
- cmp al, #0xe0
- jne int09_check_pause
- xor ax, ax
- mov ds, ax
- mov al, BYTE [0x496] ;; mf2_state |= 0x02
- or al, #0x02
- mov BYTE [0x496], al
- jmp int09_done
-
-int09_check_pause: ;; check for pause key
- cmp al, #0xe1
- jne int09_process_key
- xor ax, ax
- mov ds, ax
- mov al, BYTE [0x496] ;; mf2_state |= 0x01
- or al, #0x01
- mov BYTE [0x496], al
- jmp int09_done
-
-int09_process_key:
- mov bx, #0xf000
- mov ds, bx
- call _int09_function
-
-int09_done:
- popa
- pop ds
- cli
- call eoi_master_pic
-
-int09_finish:
- mov al, #0xAE ;;enable keyboard
- out #0x64, al
- pop ax
- iret
-
-
-;----------------------------------------
-;- INT 13h Diskette Service Entry Point -
-;----------------------------------------
-.org 0xec59
-int13_diskette:
- jmp int13_noeltorito
-
-;---------------------------------------------
-;- INT 0Eh Diskette Hardware ISR Entry Point -
-;---------------------------------------------
-.org 0xef57 ; INT 0Eh Diskette Hardware ISR Entry Point
-int0e_handler:
- push ax
- push dx
- mov dx, #0x03f4
- in al, dx
- and al, #0xc0
- cmp al, #0xc0
- je int0e_normal
- mov dx, #0x03f5
- mov al, #0x08 ; sense interrupt status
- out dx, al
-int0e_loop1:
- mov dx, #0x03f4
- in al, dx
- and al, #0xc0
- cmp al, #0xc0
- jne int0e_loop1
-int0e_loop2:
- mov dx, #0x03f5
- in al, dx
- mov dx, #0x03f4
- in al, dx
- and al, #0xc0
- cmp al, #0xc0
- je int0e_loop2
-int0e_normal:
- push ds
- xor ax, ax ;; segment 0000
- mov ds, ax
- call eoi_master_pic
- mov al, 0x043e
- or al, #0x80 ;; diskette interrupt has occurred
- mov 0x043e, al
- pop ds
- pop dx
- pop ax
- iret
-
-
-.org 0xefc7 ; Diskette Controller Parameter Table
-diskette_param_table:
-;; Since no provisions are made for multiple drive types, most
-;; values in this table are ignored. I set parameters for 1.44M
-;; floppy here
-db 0xAF
-db 0x02 ;; head load time 0000001, DMA used
-db 0x25
-db 0x02
-db 18
-db 0x1B
-db 0xFF
-db 0x6C
-db 0xF6
-db 0x0F
-db 0x08
-
-
-;----------------------------------------
-;- INT17h : Printer Service Entry Point -
-;----------------------------------------
-.org 0xefd2
-int17_handler:
- push ds
- pusha
- xor ax, ax
- mov ds, ax
- call _int17_function
- popa
- pop ds
- iret
-
-diskette_param_table2:
-;; New diskette parameter table adding 3 parameters from IBM
-;; Since no provisions are made for multiple drive types, most
-;; values in this table are ignored. I set parameters for 1.44M
-;; floppy here
-db 0xAF
-db 0x02 ;; head load time 0000001, DMA used
-db 0x25
-db 0x02
-db 18
-db 0x1B
-db 0xFF
-db 0x6C
-db 0xF6
-db 0x0F
-db 0x08
-db 79 ;; maximum track
-db 0 ;; data transfer rate
-db 4 ;; drive type in cmos
-
-.org 0xf045 ; INT 10 Functions 0-Fh Entry Point
- HALT(__LINE__)
- iret
-
-;----------
-;- INT10h -
-;----------
-.org 0xf065 ; INT 10h Video Support Service Entry Point
-int10_handler:
- ;; dont do anything, since the VGA BIOS handles int10h requests
- iret
-
-.org 0xf0a4 ; MDA/CGA Video Parameter Table (INT 1Dh)
-
-;----------
-;- INT12h -
-;----------
-.org 0xf841 ; INT 12h Memory Size Service Entry Point
-; ??? different for Pentium (machine check)?
-int12_handler:
- push ds
- mov ax, #0x0040
- mov ds, ax
- mov ax, 0x0013
- pop ds
- iret
-
-;----------
-;- INT11h -
-;----------
-.org 0xf84d ; INT 11h Equipment List Service Entry Point
-int11_handler:
- push ds
- mov ax, #0x0040
- mov ds, ax
- mov ax, 0x0010
- pop ds
- iret
-
-;----------
-;- INT15h -
-;----------
-.org 0xf859 ; INT 15h System Services Entry Point
-int15_handler:
- pushf
-#if BX_APM
- cmp ah, #0x53
- je apm_call
-#endif
- push ds
- push es
- cmp ah, #0x86
- je int15_handler32
- cmp ah, #0xE8
- je int15_handler32
- pusha
-#if BX_USE_PS2_MOUSE
- cmp ah, #0xC2
- je int15_handler_mouse
-#endif
- call _int15_function
-int15_handler_mouse_ret:
- popa
-int15_handler32_ret:
- pop es
- pop ds
- popf
- jmp iret_modify_cf
-#if BX_APM
-apm_call:
- jmp _apmreal_entry
-#endif
-
-#if BX_USE_PS2_MOUSE
-int15_handler_mouse:
- call _int15_function_mouse
- jmp int15_handler_mouse_ret
-#endif
-
-int15_handler32:
- pushad
- call _int15_function32
- popad
- jmp int15_handler32_ret
-
-;; Protected mode IDT descriptor
-;;
-;; I just make the limit 0, so the machine will shutdown
-;; if an exception occurs during protected mode memory
-;; transfers.
-;;
-;; Set base to f0000 to correspond to beginning of BIOS,
-;; in case I actually define an IDT later
-;; Set limit to 0
-
-pmode_IDT_info:
-dw 0x0000 ;; limit 15:00
-dw 0x0000 ;; base 15:00
-db 0x0f ;; base 23:16
-
-;; Real mode IDT descriptor
-;;
-;; Set to typical real-mode values.
-;; base = 000000
-;; limit = 03ff
-
-rmode_IDT_info:
-dw 0x03ff ;; limit 15:00
-dw 0x0000 ;; base 15:00
-db 0x00 ;; base 23:16
-
-
-;----------
-;- INT1Ah -
-;----------
-.org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point
-int1a_handler:
-#if BX_PCIBIOS
- cmp ah, #0xb1
- jne int1a_normal
- call pcibios_real
- jc pcibios_error
- retf 2
-pcibios_error:
- mov bl, ah
- mov ah, #0xb1
- push ds
- pusha
- mov ax, ss ; set readable descriptor to ds, for calling pcibios
- mov ds, ax ; on 16bit protected mode.
- jmp int1a_callfunction
-int1a_normal:
-#endif
- push ds
- pusha
- xor ax, ax
- mov ds, ax
-int1a_callfunction:
- call _int1a_function
- popa
- pop ds
- iret
-
-;;
-;; int70h: IRQ8 - CMOS RTC
-;;
-int70_handler:
- push ds
- pushad
- xor ax, ax
- mov ds, ax
- call _int70_function
- popad
- pop ds
- iret
-
-;---------
-;- INT08 -
-;---------
-.org 0xfea5 ; INT 08h System Timer ISR Entry Point
-int08_handler:
- sti
- push eax
- push ds
- xor ax, ax
- mov ds, ax
-
- ;; time to turn off drive(s)?
- mov al,0x0440
- or al,al
- jz int08_floppy_off
- dec al
- mov 0x0440,al
- jnz int08_floppy_off
- ;; turn motor(s) off
- push dx
- mov dx,#0x03f2
- in al,dx
- and al,#0xcf
- out dx,al
- pop dx
-int08_floppy_off:
-
- mov eax, 0x046c ;; get ticks dword
- inc eax
-
- ;; compare eax to one days worth of timer ticks at 18.2 hz
- cmp eax, #0x001800B0
- jb int08_store_ticks
- ;; there has been a midnight rollover at this point
- xor eax, eax ;; zero out counter
- inc BYTE 0x0470 ;; increment rollover flag
-
-int08_store_ticks:
- mov 0x046c, eax ;; store new ticks dword
- ;; chain to user timer tick INT #0x1c
- //pushf
- //;; call_ep [ds:loc]
- //CALL_EP( 0x1c << 2 )
- int #0x1c
- cli
- call eoi_master_pic
- pop ds
- pop eax
- iret
-
-.org 0xfef3 ; Initial Interrupt Vector Offsets Loaded by POST
-
-
-.org 0xff00
-.ascii BIOS_COPYRIGHT_STRING
-
-;------------------------------------------------
-;- IRET Instruction for Dummy Interrupt Handler -
-;------------------------------------------------
-.org 0xff53 ; IRET Instruction for Dummy Interrupt Handler
-dummy_iret_handler:
- iret
-
-.org 0xff54 ; INT 05h Print Screen Service Entry Point
- HALT(__LINE__)
- iret
-
-.org 0xfff0 ; Power-up Entry Point
- jmp 0xf000:post
-
-.org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
-.ascii BIOS_BUILD_DATE
-
-.org 0xfffe ; System Model ID
-db SYS_MODEL_ID
-db 0x00 ; filler
-
-.org 0xfa6e ;; Character Font for 320x200 & 640x200 Graphics (lower 128 characters)
-ASM_END
-/*
- * This font comes from the fntcol16.zip package (c) by Joseph Gil
- * found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
- * This font is public domain
- */
-static Bit8u vgafont8[128*8]=
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
- 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
- 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
- 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
- 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
- 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
- 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
- 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
- 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
- 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
- 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
- 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
- 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
- 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
- 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
- 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
- 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
- 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
- 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
- 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
- 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
- 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
- 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
- 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
- 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
- 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
- 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
- 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
- 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
- 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
- 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
- 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
- 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
- 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
- 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
- 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
- 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
- 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
- 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
- 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
- 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
- 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
- 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
- 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
- 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
- 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
- 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
- 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
- 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
- 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
- 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
- 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
- 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
- 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
- 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
- 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00,
- 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
- 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
- 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
- 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
- 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
- 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
- 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
- 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
- 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
- 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
- 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
- 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
- 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
- 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
- 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
- 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
- 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
- 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
- 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
- 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
- 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
- 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
- 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
- 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
- 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
- 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
- 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
- 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
- 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
- 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
- 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
- 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
- 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
- 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
- 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
- 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
- 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
- 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
- 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
- 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
- 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
- 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
- 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
- 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
- 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
- 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
- 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
- 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
- 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
- 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
- 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
- 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
- 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
- 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
- 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
- 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
- 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
- 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
- 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
-};
-
-ASM_START
-.org 0xcc00
-bios_table_area_end:
-// bcc-generated data will be placed here
-ASM_END
diff --git a/kvm/bios/rombios.h b/kvm/bios/rombios.h
deleted file mode 100644
index c8f64f3f5..000000000
--- a/kvm/bios/rombios.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id: rombios.h,v 1.4 2007/02/20 09:36:55 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2006 Volker Ruppert
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-/* define it to include QEMU specific code */
-#define BX_QEMU
-
-#ifndef LEGACY
-# define BX_ROMBIOS32 1
-#else
-# define BX_ROMBIOS32 0
-#endif
-#define DEBUG_ROMBIOS 0
-
-#define PANIC_PORT 0x400
-#define PANIC_PORT2 0x401
-#define INFO_PORT 0x402
-#define DEBUG_PORT 0x403
-
-#define BIOS_PRINTF_HALT 1
-#define BIOS_PRINTF_SCREEN 2
-#define BIOS_PRINTF_INFO 4
-#define BIOS_PRINTF_DEBUG 8
-#define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
-#define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
-
-#define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
-
-// Defines the output macros.
-// BX_DEBUG goes to INFO port until we can easily choose debug info on a
-// per-device basis. Debug info are sent only in debug mode
-#if DEBUG_ROMBIOS
-# define BX_DEBUG(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
-#else
-# define BX_DEBUG(format, p...)
-#endif
-#define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
-#define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
-
-#define ACPI_DATA_SIZE 0x00010000L
-#define PM_IO_BASE 0xb000
-#define SMB_IO_BASE 0xb100
-#define SMP_MSR_ADDR 0x0510
-#define APIC_MADT_PTR 0x0514
-
-#define MAX_CPUS 16
-
-#define QEMU_CFG_CTL_PORT 0x510
-#define QEMU_CFG_DATA_PORT 0x511
-#define QEMU_CFG_SIGNATURE 0x00
-#define QEMU_CFG_ID 0x01
-#define QEMU_CFG_UUID 0x02
-#define QEMU_CFG_NUMA 0x0d
-#define QEMU_CFG_BOOT_MENU 0x0e
-#define QEMU_CFG_ARCH_LOCAL 0x8000
-#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
-#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
-#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
-
- // Define the application NAME
-#if defined(BX_QEMU)
-# define BX_APPNAME "QEMU"
-#elif defined(PLEX86)
-# define BX_APPNAME "Plex86"
-#else
-# define BX_APPNAME "Bochs"
-#endif
diff --git a/kvm/bios/rombios32.c b/kvm/bios/rombios32.c
deleted file mode 100755
index 0b3556cba..000000000
--- a/kvm/bios/rombios32.c
+++ /dev/null
@@ -1,2749 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id: rombios32.c,v 1.11 2007/08/03 13:56:13 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// 32 bit Bochs BIOS init code
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include <stdarg.h>
-#include <stddef.h>
-
-#include "rombios.h"
-
-typedef signed char int8_t;
-typedef short int16_t;
-typedef int int32_t;
-typedef long long int64_t;
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
-
-/* if true, put the MP float table and ACPI RSDT in EBDA and the MP
- table in RAM. Unfortunately, Linux has bugs with that, so we prefer
- to modify the BIOS in shadow RAM */
-//#define BX_USE_EBDA_TABLES
-
-/* define it if the (emulated) hardware supports SMM mode */
-//#define BX_USE_SMM
-
-#define cpuid(index, eax, ebx, ecx, edx) \
- asm volatile ("cpuid" \
- : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
- : "0" (index))
-
-#define wbinvd() asm volatile("wbinvd")
-
-#define CPUID_MSR (1 << 5)
-#define CPUID_APIC (1 << 9)
-#define CPUID_MTRR (1 << 12)
-
-#define APIC_BASE ((uint8_t *)0xfee00000)
-#define APIC_ICR_LOW 0x300
-#define APIC_SVR 0x0F0
-#define APIC_ID 0x020
-#define APIC_LVT3 0x370
-
-/* IRQs 5,9,10,11 */
-#define PCI_ISA_IRQ_MASK 0x0e20U
-
-#define APIC_ENABLED 0x0100
-
-#define AP_BOOT_ADDR 0x9f000
-
-#define MPTABLE_MAX_SIZE 0x00002000
-#define SMI_CMD_IO_ADDR 0xb2
-
-#define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
-
-#define MSR_MTRRcap 0x000000fe
-#define MSR_MTRRfix64K_00000 0x00000250
-#define MSR_MTRRfix16K_80000 0x00000258
-#define MSR_MTRRfix16K_A0000 0x00000259
-#define MSR_MTRRfix4K_C0000 0x00000268
-#define MSR_MTRRfix4K_C8000 0x00000269
-#define MSR_MTRRfix4K_D0000 0x0000026a
-#define MSR_MTRRfix4K_D8000 0x0000026b
-#define MSR_MTRRfix4K_E0000 0x0000026c
-#define MSR_MTRRfix4K_E8000 0x0000026d
-#define MSR_MTRRfix4K_F0000 0x0000026e
-#define MSR_MTRRfix4K_F8000 0x0000026f
-#define MSR_MTRRdefType 0x000002ff
-
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-#define MAX_INT_OVERRIDES 16
-
-static inline void outl(int addr, int val)
-{
- asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val));
-}
-
-static inline void outw(int addr, int val)
-{
- asm volatile ("outw %w1, %w0" : : "d" (addr), "a" (val));
-}
-
-static inline void outb(int addr, int val)
-{
- asm volatile ("outb %b1, %w0" : : "d" (addr), "a" (val));
-}
-
-static inline uint32_t inl(int addr)
-{
- uint32_t val;
- asm volatile ("inl %w1, %0" : "=a" (val) : "d" (addr));
- return val;
-}
-
-static inline uint16_t inw(int addr)
-{
- uint16_t val;
- asm volatile ("inw %w1, %w0" : "=a" (val) : "d" (addr));
- return val;
-}
-
-static inline uint8_t inb(int addr)
-{
- uint8_t val;
- asm volatile ("inb %w1, %b0" : "=a" (val) : "d" (addr));
- return val;
-}
-
-static inline void writel(void *addr, uint32_t val)
-{
- *(volatile uint32_t *)addr = val;
-}
-
-static inline void writew(void *addr, uint16_t val)
-{
- *(volatile uint16_t *)addr = val;
-}
-
-static inline void writeb(void *addr, uint8_t val)
-{
- *(volatile uint8_t *)addr = val;
-}
-
-static inline uint32_t readl(const void *addr)
-{
- return *(volatile const uint32_t *)addr;
-}
-
-static inline uint16_t readw(const void *addr)
-{
- return *(volatile const uint16_t *)addr;
-}
-
-static inline uint8_t readb(const void *addr)
-{
- return *(volatile const uint8_t *)addr;
-}
-
-static inline void putc(int c)
-{
- outb(INFO_PORT, c);
-}
-
-static uint64_t rdmsr(unsigned index)
-{
- unsigned long long ret;
-
- asm ("rdmsr" : "=A"(ret) : "c"(index));
- return ret;
-}
-
-static void wrmsr(unsigned index, uint64_t val)
-{
- asm volatile ("wrmsr" : : "c"(index), "A"(val));
-}
-
-static inline int isdigit(int c)
-{
- return c >= '0' && c <= '9';
-}
-
-void *memset(void *d1, int val, size_t len)
-{
- uint8_t *d = d1;
-
- while (len--) {
- *d++ = val;
- }
- return d1;
-}
-
-void *memcpy(void *d1, const void *s1, size_t len)
-{
- uint8_t *d = d1;
- const uint8_t *s = s1;
-
- while (len--) {
- *d++ = *s++;
- }
- return d1;
-}
-
-void *memmove(void *d1, const void *s1, size_t len)
-{
- uint8_t *d = d1;
- const uint8_t *s = s1;
-
- if (d <= s) {
- while (len--) {
- *d++ = *s++;
- }
- } else {
- d += len;
- s += len;
- while (len--) {
- *--d = *--s;
- }
- }
- return d1;
-}
-
-int memcmp(const void *s1, const void *s2, size_t len)
-{
- const int8_t *p1 = s1;
- const int8_t *p2 = s2;
-
- while (len--) {
- int r = *p1++ - *p2++;
- if(r)
- return r;
- }
-
- return 0;
-}
-
-size_t strlen(const char *s)
-{
- const char *s1;
- for(s1 = s; *s1 != '\0'; s1++);
- return s1 - s;
-}
-
-/* from BSD ppp sources */
-int vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
-{
- int c, i, n;
- int width, prec, fillch;
- int base, len, neg;
- unsigned long val = 0;
- const char *f;
- char *str, *buf0;
- char num[32];
- static const char hexchars[] = "0123456789abcdef";
-
- buf0 = buf;
- --buflen;
- while (buflen > 0) {
- for (f = fmt; *f != '%' && *f != 0; ++f)
- ;
- if (f > fmt) {
- len = f - fmt;
- if (len > buflen)
- len = buflen;
- memcpy(buf, fmt, len);
- buf += len;
- buflen -= len;
- fmt = f;
- }
- if (*fmt == 0)
- break;
- c = *++fmt;
- width = prec = 0;
- fillch = ' ';
- if (c == '0') {
- fillch = '0';
- c = *++fmt;
- }
- if (c == '*') {
- width = va_arg(args, int);
- c = *++fmt;
- } else {
- while (isdigit(c)) {
- width = width * 10 + c - '0';
- c = *++fmt;
- }
- }
- if (c == '.') {
- c = *++fmt;
- if (c == '*') {
- prec = va_arg(args, int);
- c = *++fmt;
- } else {
- while (isdigit(c)) {
- prec = prec * 10 + c - '0';
- c = *++fmt;
- }
- }
- }
- /* modifiers */
- switch(c) {
- case 'l':
- c = *++fmt;
- break;
- default:
- break;
- }
- str = 0;
- base = 0;
- neg = 0;
- ++fmt;
- switch (c) {
- case 'd':
- i = va_arg(args, int);
- if (i < 0) {
- neg = 1;
- val = -i;
- } else
- val = i;
- base = 10;
- break;
- case 'o':
- val = va_arg(args, unsigned int);
- base = 8;
- break;
- case 'x':
- case 'X':
- val = va_arg(args, unsigned int);
- base = 16;
- break;
- case 'p':
- val = (unsigned long) va_arg(args, void *);
- base = 16;
- neg = 2;
- break;
- case 's':
- str = va_arg(args, char *);
- break;
- case 'c':
- num[0] = va_arg(args, int);
- num[1] = 0;
- str = num;
- break;
- default:
- *buf++ = '%';
- if (c != '%')
- --fmt; /* so %z outputs %z etc. */
- --buflen;
- continue;
- }
- if (base != 0) {
- str = num + sizeof(num);
- *--str = 0;
- while (str > num + neg) {
- *--str = hexchars[val % base];
- val = val / base;
- if (--prec <= 0 && val == 0)
- break;
- }
- switch (neg) {
- case 1:
- *--str = '-';
- break;
- case 2:
- *--str = 'x';
- *--str = '0';
- break;
- }
- len = num + sizeof(num) - 1 - str;
- } else {
- len = strlen(str);
- if (prec > 0 && len > prec)
- len = prec;
- }
- if (width > 0) {
- if (width > buflen)
- width = buflen;
- if ((n = width - len) > 0) {
- buflen -= n;
- for (; n > 0; --n)
- *buf++ = fillch;
- }
- }
- if (len > buflen)
- len = buflen;
- memcpy(buf, str, len);
- buf += len;
- buflen -= len;
- }
- *buf = 0;
- return buf - buf0;
-}
-
-int snprintf(char * buf, size_t size, const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- i=vsnprintf(buf,size,fmt,args);
- va_end(args);
- return i;
-}
-
-void bios_printf(int flags, const char *fmt, ...)
-{
- va_list ap;
- char buf[1024];
- const char *s;
-
- if ((flags & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT)
- outb(PANIC_PORT2, 0x00);
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- s = buf;
- while (*s)
- putc(*s++);
- va_end(ap);
-}
-
-void delay_ms(int n)
-{
- int i, j;
- for(i = 0; i < n; i++) {
-#ifdef BX_QEMU
- /* approximative ! */
- for(j = 0; j < 1000000; j++);
-#else
- {
- int r1, r2;
- j = 66;
- r1 = inb(0x61) & 0x10;
- do {
- r2 = inb(0x61) & 0x10;
- if (r1 != r2) {
- j--;
- r1 = r2;
- }
- } while (j > 0);
- }
-#endif
- }
-}
-
-uint16_t smp_cpus;
-uint32_t cpuid_signature;
-uint32_t cpuid_features;
-uint32_t cpuid_ext_features;
-unsigned long ram_size;
-uint64_t ram_end;
-#ifdef BX_QEMU
-uint8_t irq0_override;
-#endif
-#ifdef BX_USE_EBDA_TABLES
-unsigned long ebda_cur_addr;
-#endif
-int acpi_enabled;
-uint32_t pm_io_base, smb_io_base;
-int pm_sci_int;
-unsigned long bios_table_cur_addr;
-unsigned long bios_table_end_addr;
-
-void init_smp_msrs(void)
-{
- *(uint32_t *)SMP_MSR_ADDR = 0;
-}
-
-static inline uint64_t le64_to_cpu(uint64_t x)
-{
- return x;
-}
-
-void wrmsr_smp(uint32_t index, uint64_t val)
-{
- static struct { uint32_t ecx, eax, edx; } *p = (void *)SMP_MSR_ADDR;
-
- wrmsr(index, val);
- p->ecx = index;
- p->eax = val;
- p->edx = val >> 32;
- ++p;
- p->ecx = 0;
-}
-
-#ifdef BX_QEMU
-
-int qemu_cfg_port;
-
-void qemu_cfg_select(int f)
-{
- outw(QEMU_CFG_CTL_PORT, f);
-}
-
-int qemu_cfg_port_probe()
-{
- char *sig = "QEMU";
- int i;
-
- qemu_cfg_select(QEMU_CFG_SIGNATURE);
-
- for (i = 0; i < 4; i++)
- if (inb(QEMU_CFG_DATA_PORT) != sig[i])
- return 0;
-
- return 1;
-}
-
-void qemu_cfg_read(uint8_t *buf, int len)
-{
- while (len--)
- *(buf++) = inb(QEMU_CFG_DATA_PORT);
-}
-
-static uint16_t acpi_additional_tables(void)
-{
- uint16_t cnt;
-
- qemu_cfg_select(QEMU_CFG_ACPI_TABLES);
- qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt));
-
- return cnt;
-}
-
-static int acpi_load_table(int i, uint32_t addr, uint16_t *len)
-{
- qemu_cfg_read((uint8_t*)len, sizeof(*len));
-
- if (!*len)
- return -1;
-
- qemu_cfg_read((uint8_t*)addr, *len);
- return 0;
-}
-
-static uint16_t smbios_entries(void)
-{
- uint16_t cnt;
-
- qemu_cfg_select(QEMU_CFG_SMBIOS_ENTRIES);
- qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt));
-
- return cnt;
-}
-
-uint64_t qemu_cfg_get64 (void)
-{
- uint64_t ret;
-
- qemu_cfg_read((uint8_t*)&ret, 8);
- return le64_to_cpu(ret);
-}
-#endif
-
-#ifdef BX_QEMU
-void irq0_override_probe(void)
-{
- if(qemu_cfg_port) {
- qemu_cfg_select(QEMU_CFG_IRQ0_OVERRIDE);
- qemu_cfg_read(&irq0_override, 1);
- }
-}
-#endif
-
-void cpu_probe(void)
-{
- uint32_t eax, ebx, ecx, edx;
- cpuid(1, eax, ebx, ecx, edx);
- cpuid_signature = eax;
- cpuid_features = edx;
- cpuid_ext_features = ecx;
-}
-
-static int cmos_readb(int addr)
-{
- outb(0x70, addr);
- return inb(0x71);
-}
-
-void setup_mtrr(void)
-{
- int i, vcnt, fix, wc;
- uint32_t mtrr_cap;
- union {
- uint8_t valb[8];
- uint64_t val;
- } u;
-
- if (!(cpuid_features & CPUID_MTRR))
- return;
-
- if (!(cpuid_features & CPUID_MSR))
- return;
-
- mtrr_cap = rdmsr(MSR_MTRRcap);
- vcnt = mtrr_cap & 0xff;
- fix = mtrr_cap & 0x100;
- wc = mtrr_cap & 0x400;
- if (!vcnt || !fix)
- return;
-
- u.val = 0;
- for (i = 0; i < 8; ++i)
- if (ram_size >= 65536 * (i + 1))
- u.valb[i] = 6;
- wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
- u.val = 0;
- for (i = 0; i < 8; ++i)
- if (ram_size >= 65536 * 8 + 16384 * (i + 1))
- u.valb[i] = 6;
- wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
- wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
- wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
- wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
- wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
- wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
- wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
- wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
- wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
- wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
- /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
- wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0);
- wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800);
- wrmsr_smp(MSR_MTRRdefType, 0xc06);
-}
-
-void ram_probe(void)
-{
- if (cmos_readb(0x34) | cmos_readb(0x35))
- ram_size = (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 +
- 16 * 1024 * 1024;
- else
- ram_size = (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024;
-
- if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d))
- ram_end = (((uint64_t)cmos_readb(0x5b) << 16) |
- ((uint64_t)cmos_readb(0x5c) << 24) |
- ((uint64_t)cmos_readb(0x5d) << 32)) + (1ull << 32);
- else
- ram_end = ram_size;
-
- BX_INFO("end of ram=%ldMB\n", ram_end >> 20);
-
- BX_INFO("ram_size=0x%08lx\n", ram_size);
-#ifdef BX_USE_EBDA_TABLES
- ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
- BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
-#endif
-}
-
-/****************************************************/
-/* SMP probe */
-
-extern uint8_t smp_ap_boot_code_start;
-extern uint8_t smp_ap_boot_code_end;
-
-/* find the number of CPUs by launching a SIPI to them */
-void smp_probe(void)
-{
- uint32_t val, sipi_vector;
-
- writew(&smp_cpus, 1);
- if (cpuid_features & CPUID_APIC) {
-
- /* enable local APIC */
- val = readl(APIC_BASE + APIC_SVR);
- val |= APIC_ENABLED;
- writel(APIC_BASE + APIC_SVR, val);
-
- /* copy AP boot code */
- memcpy((void *)AP_BOOT_ADDR, &smp_ap_boot_code_start,
- &smp_ap_boot_code_end - &smp_ap_boot_code_start);
-
- /* broadcast SIPI */
- writel(APIC_BASE + APIC_ICR_LOW, 0x000C4500);
- sipi_vector = AP_BOOT_ADDR >> 12;
- writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector);
-
-#ifndef BX_QEMU
- delay_ms(10);
-#else
- while (cmos_readb(0x5f) + 1 != readw(&smp_cpus))
- ;
-#endif
- }
- BX_INFO("Found %d cpu(s)\n", readw(&smp_cpus));
-}
-
-/****************************************************/
-/* PCI init */
-
-#define PCI_ADDRESS_SPACE_MEM 0x00
-#define PCI_ADDRESS_SPACE_IO 0x01
-#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
-
-#define PCI_ROM_SLOT 6
-#define PCI_NUM_REGIONS 7
-
-#define PCI_DEVICES_MAX 64
-
-#define PCI_VENDOR_ID 0x00 /* 16 bits */
-#define PCI_DEVICE_ID 0x02 /* 16 bits */
-#define PCI_COMMAND 0x04 /* 16 bits */
-#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
-#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
-#define PCI_CLASS_DEVICE 0x0a /* Device class */
-#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
-#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
-#define PCI_MIN_GNT 0x3e /* 8 bits */
-#define PCI_MAX_LAT 0x3f /* 8 bits */
-
-#define PCI_VENDOR_ID_INTEL 0x8086
-#define PCI_DEVICE_ID_INTEL_82441 0x1237
-#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
-#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
-#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110
-#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
-#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
-
-#define PCI_VENDOR_ID_IBM 0x1014
-#define PCI_VENDOR_ID_APPLE 0x106b
-
-typedef struct PCIDevice {
- int bus;
- int devfn;
-} PCIDevice;
-
-static uint32_t pci_bios_io_addr;
-static uint32_t pci_bios_mem_addr;
-static uint32_t pci_bios_bigmem_addr;
-/* host irqs corresponding to PCI irqs A-D */
-static uint8_t pci_irqs[4] = { 10, 10, 11, 11 };
-static PCIDevice i440_pcidev;
-
-static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
-{
- outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
- outl(0xcfc, val);
-}
-
-static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
-{
- outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
- outw(0xcfc + (addr & 2), val);
-}
-
-static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
-{
- outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
- outb(0xcfc + (addr & 3), val);
-}
-
-static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
-{
- outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
- return inl(0xcfc);
-}
-
-static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
-{
- outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
- return inw(0xcfc + (addr & 2));
-}
-
-static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
-{
- outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc));
- return inb(0xcfc + (addr & 3));
-}
-
-static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
-{
- uint16_t cmd;
- uint32_t ofs, old_addr;
-
- if ( region_num == PCI_ROM_SLOT ) {
- ofs = 0x30;
- }else{
- ofs = 0x10 + region_num * 4;
- }
-
- old_addr = pci_config_readl(d, ofs);
-
- pci_config_writel(d, ofs, addr);
- BX_INFO("region %d: 0x%08x\n", region_num, addr);
-
- /* enable memory mappings */
- cmd = pci_config_readw(d, PCI_COMMAND);
- if ( region_num == PCI_ROM_SLOT )
- cmd |= 2;
- else if (old_addr & PCI_ADDRESS_SPACE_IO)
- cmd |= 1;
- else
- cmd |= 2;
- pci_config_writew(d, PCI_COMMAND, cmd);
-}
-
-/* return the global irq number corresponding to a given device irq
- pin. We could also use the bus number to have a more precise
- mapping. */
-static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
- int slot_addend;
- slot_addend = (pci_dev->devfn >> 3) - 1;
- return (irq_num + slot_addend) & 3;
-}
-
-static void find_bios_table_area(void)
-{
- unsigned long addr;
- for(addr = 0xf0000; addr < 0x100000; addr += 16) {
- if (*(uint32_t *)addr == 0xaafb4442) {
- bios_table_cur_addr = addr + 8;
- bios_table_end_addr = bios_table_cur_addr + *(uint32_t *)(addr + 4);
- BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n",
- bios_table_cur_addr, bios_table_end_addr);
- return;
- }
- }
- return;
-}
-
-static void bios_shadow_init(PCIDevice *d)
-{
- int v;
-
- if (bios_table_cur_addr == 0)
- return;
-
- /* remap the BIOS to shadow RAM an keep it read/write while we
- are writing tables */
- v = pci_config_readb(d, 0x59);
- v &= 0xcf;
- pci_config_writeb(d, 0x59, v);
- memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000);
- v |= 0x30;
- pci_config_writeb(d, 0x59, v);
- memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000);
-
- i440_pcidev = *d;
-}
-
-static void bios_lock_shadow_ram(void)
-{
- PCIDevice *d = &i440_pcidev;
- int v;
-
- wbinvd();
- v = pci_config_readb(d, 0x59);
- v = (v & 0x0f) | (0x10);
- pci_config_writeb(d, 0x59, v);
-}
-
-static void pci_bios_init_bridges(PCIDevice *d)
-{
- uint16_t vendor_id, device_id;
-
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
-
- if (vendor_id == PCI_VENDOR_ID_INTEL &&
- (device_id == PCI_DEVICE_ID_INTEL_82371SB_0 ||
- device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
- int i, irq;
- uint8_t elcr[2];
-
- /* PIIX3/PIIX4 PCI to ISA bridge */
-
- elcr[0] = 0x00;
- elcr[1] = 0x00;
- for(i = 0; i < 4; i++) {
- irq = pci_irqs[i];
- /* set to trigger level */
- elcr[irq >> 3] |= (1 << (irq & 7));
- /* activate irq remapping in PIIX */
- pci_config_writeb(d, 0x60 + i, irq);
- }
- outb(0x4d0, elcr[0]);
- outb(0x4d1, elcr[1]);
- BX_INFO("PIIX3/PIIX4 init: elcr=%02x %02x\n",
- elcr[0], elcr[1]);
- } else if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441) {
- /* i440 PCI bridge */
- bios_shadow_init(d);
- }
-}
-
-extern uint8_t smm_relocation_start, smm_relocation_end;
-extern uint8_t smm_code_start, smm_code_end;
-
-#ifdef BX_USE_SMM
-static void smm_init(PCIDevice *d)
-{
- uint32_t value;
-
- /* check if SMM init is already done */
- value = pci_config_readl(d, 0x58);
- if ((value & (1 << 25)) == 0) {
-
- /* enable the SMM memory window */
- pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48);
-
- /* save original memory content */
- memcpy((void *)0xa8000, (void *)0x38000, 0x8000);
-
- /* copy the SMM relocation code */
- memcpy((void *)0x38000, &smm_relocation_start,
- &smm_relocation_end - &smm_relocation_start);
-
- /* enable SMI generation when writing to the APMC register */
- pci_config_writel(d, 0x58, value | (1 << 25));
-
- /* init APM status port */
- outb(0xb3, 0x01);
-
- /* raise an SMI interrupt */
- outb(0xb2, 0x00);
-
- /* wait until SMM code executed */
- while (inb(0xb3) != 0x00);
-
- /* restore original memory content */
- memcpy((void *)0x38000, (void *)0xa8000, 0x8000);
-
- /* copy the SMM code */
- memcpy((void *)0xa8000, &smm_code_start,
- &smm_code_end - &smm_code_start);
- wbinvd();
-
- /* close the SMM memory window and enable normal SMM */
- pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08);
- }
-}
-#endif
-
-static void piix4_pm_enable(PCIDevice *d)
-{
- /* PIIX4 Power Management device (for ACPI) */
- pci_config_writel(d, 0x40, PM_IO_BASE | 1);
- pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */
- pci_config_writel(d, 0x90, SMB_IO_BASE | 1);
- pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */
-#ifdef BX_USE_SMM
- smm_init(d);
-#endif
-}
-
-static void pci_bios_init_device(PCIDevice *d)
-{
- int class;
- uint32_t *paddr;
- int i, pin, pic_irq, vendor_id, device_id;
-
- class = pci_config_readw(d, PCI_CLASS_DEVICE);
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
- BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x class=0x%04x\n",
- d->bus, d->devfn, vendor_id, device_id, class);
- switch(class) {
- case 0x0101: /* Mass storage controller - IDE interface */
- if (vendor_id == PCI_VENDOR_ID_INTEL &&
- (device_id == PCI_DEVICE_ID_INTEL_82371SB_1 ||
- device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
- /* PIIX3/PIIX4 IDE */
- pci_config_writew(d, 0x40, 0x8000); // enable IDE0
- pci_config_writew(d, 0x42, 0x8000); // enable IDE1
- goto default_map;
- } else {
- /* IDE: we map it as in ISA mode */
- pci_set_io_region_addr(d, 0, 0x1f0);
- pci_set_io_region_addr(d, 1, 0x3f4);
- pci_set_io_region_addr(d, 2, 0x170);
- pci_set_io_region_addr(d, 3, 0x374);
- }
- break;
- case 0x0300: /* Display controller - VGA compatible controller */
- if (vendor_id != 0x1234)
- goto default_map;
- /* VGA: map frame buffer to default Bochs VBE address */
- pci_set_io_region_addr(d, 0, 0xE0000000);
- break;
- case 0x0800: /* Generic system peripheral - PIC */
- if (vendor_id == PCI_VENDOR_ID_IBM) {
- /* IBM */
- if (device_id == 0x0046 || device_id == 0xFFFF) {
- /* MPIC & MPIC2 */
- pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
- }
- }
- break;
- case 0xff00:
- if (vendor_id == PCI_VENDOR_ID_APPLE &&
- (device_id == 0x0017 || device_id == 0x0022)) {
- /* macio bridge */
- pci_set_io_region_addr(d, 0, 0x80800000);
- }
- break;
- default:
- default_map:
- /* default memory mappings */
- for(i = 0; i < PCI_NUM_REGIONS; i++) {
- int ofs;
- uint32_t val, size ;
-
- if (i == PCI_ROM_SLOT)
- ofs = 0x30;
- else
- ofs = 0x10 + i * 4;
- pci_config_writel(d, ofs, 0xffffffff);
- val = pci_config_readl(d, ofs);
- if (val != 0) {
- size = (~(val & ~0xf)) + 1;
- if (val & PCI_ADDRESS_SPACE_IO)
- paddr = &pci_bios_io_addr;
- else if (size >= 0x04000000)
- paddr = &pci_bios_bigmem_addr;
- else
- paddr = &pci_bios_mem_addr;
- *paddr = (*paddr + size - 1) & ~(size - 1);
- pci_set_io_region_addr(d, i, *paddr);
- *paddr += size;
- /* make memory address page aligned */
- if (!(val & PCI_ADDRESS_SPACE_IO))
- *paddr = (*paddr + 0xfff) & 0xfffff000;
- }
- }
- break;
- }
-
- /* map the interrupt */
- pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
- if (pin != 0) {
- pin = pci_slot_get_pirq(d, pin - 1);
- pic_irq = pci_irqs[pin];
- pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
- }
-
- if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
- /* PIIX4 Power Management device (for ACPI) */
-
- // acpi sci is hardwired to 9
- pci_config_writeb(d, PCI_INTERRUPT_LINE, 9);
-
- pm_io_base = PM_IO_BASE;
- smb_io_base = SMB_IO_BASE;
- pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE);
- piix4_pm_enable(d);
- acpi_enabled = 1;
- }
-}
-
-void pci_for_each_device(void (*init_func)(PCIDevice *d))
-{
- PCIDevice d1, *d = &d1;
- int bus, devfn;
- uint16_t vendor_id, device_id;
-
- for(bus = 0; bus < 1; bus++) {
- for(devfn = 0; devfn < 256; devfn++) {
- d->bus = bus;
- d->devfn = devfn;
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
- if (vendor_id != 0xffff || device_id != 0xffff) {
- init_func(d);
- }
- }
- }
-}
-
-void pci_bios_init(void)
-{
- pci_bios_io_addr = 0xc000;
- pci_bios_mem_addr = 0xf0000000;
- pci_bios_bigmem_addr = ram_size;
- if (pci_bios_bigmem_addr < 0x90000000)
- pci_bios_bigmem_addr = 0x90000000;
-
- pci_for_each_device(pci_bios_init_bridges);
-
- pci_for_each_device(pci_bios_init_device);
-}
-
-/****************************************************/
-/* Multi Processor table init */
-
-static void putb(uint8_t **pp, int val)
-{
- uint8_t *q;
- q = *pp;
- *q++ = val;
- *pp = q;
-}
-
-static void putstr(uint8_t **pp, const char *str)
-{
- uint8_t *q;
- q = *pp;
- while (*str)
- *q++ = *str++;
- *pp = q;
-}
-
-static void putle16(uint8_t **pp, int val)
-{
- uint8_t *q;
- q = *pp;
- *q++ = val;
- *q++ = val >> 8;
- *pp = q;
-}
-
-static void putle32(uint8_t **pp, int val)
-{
- uint8_t *q;
- q = *pp;
- *q++ = val;
- *q++ = val >> 8;
- *q++ = val >> 16;
- *q++ = val >> 24;
- *pp = q;
-}
-
-static int mpf_checksum(const uint8_t *data, int len)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < len; i++)
- sum += data[i];
- return sum & 0xff;
-}
-
-static unsigned long align(unsigned long addr, unsigned long v)
-{
- return (addr + v - 1) & ~(v - 1);
-}
-
-static void mptable_init(void)
-{
- uint8_t *mp_config_table, *q, *float_pointer_struct;
- int ioapic_id, i, len;
- int mp_config_table_size;
-
-#ifdef BX_USE_EBDA_TABLES
- mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE);
-#else
- bios_table_cur_addr = align(bios_table_cur_addr, 16);
- mp_config_table = (uint8_t *)bios_table_cur_addr;
-#endif
- q = mp_config_table;
- putstr(&q, "PCMP"); /* "PCMP signature */
- putle16(&q, 0); /* table length (patched later) */
- putb(&q, 4); /* spec rev */
- putb(&q, 0); /* checksum (patched later) */
-#ifdef BX_QEMU
- putstr(&q, "QEMUCPU "); /* OEM id */
-#else
- putstr(&q, "BOCHSCPU");
-#endif
- putstr(&q, "0.1 "); /* vendor id */
- putle32(&q, 0); /* OEM table ptr */
- putle16(&q, 0); /* OEM table size */
-#ifdef BX_QEMU
- if (irq0_override)
- putle16(&q, MAX_CPUS + 17); /* entry count */
- else
- putle16(&q, MAX_CPUS + 18); /* entry count */
-#else
- putle16(&q, MAX_CPUS + 18); /* entry count */
-#endif
- putle32(&q, 0xfee00000); /* local APIC addr */
- putle16(&q, 0); /* ext table length */
- putb(&q, 0); /* ext table checksum */
- putb(&q, 0); /* reserved */
-
- for(i = 0; i < MAX_CPUS ; i++) {
- putb(&q, 0); /* entry type = processor */
- putb(&q, i); /* APIC id */
- putb(&q, 0x11); /* local APIC version number */
- if (i == 0)
- putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
- else if ( i < smp_cpus)
- putb(&q, 1); /* cpu flags: enabled */
- else
- putb(&q, 0); /* cpu flags: disabled */
- putb(&q, 0); /* cpu signature */
- putb(&q, 6);
- putb(&q, 0);
- putb(&q, 0);
- putle16(&q, 0x201); /* feature flags */
- putle16(&q, 0);
-
- putle16(&q, 0); /* reserved */
- putle16(&q, 0);
- putle16(&q, 0);
- putle16(&q, 0);
- }
-
- /* isa bus */
- putb(&q, 1); /* entry type = bus */
- putb(&q, 0); /* bus ID */
- putstr(&q, "ISA ");
-
- /* ioapic */
- ioapic_id = smp_cpus;
- putb(&q, 2); /* entry type = I/O APIC */
- putb(&q, ioapic_id); /* apic ID */
- putb(&q, 0x11); /* I/O APIC version number */
- putb(&q, 1); /* enable */
- putle32(&q, 0xfec00000); /* I/O APIC addr */
-
- /* irqs */
- for(i = 0; i < 16; i++) {
-#ifdef BX_QEMU
- /* One entry per ioapic interrupt destination. Destination 2 is covered
- * by irq0->inti2 override (i == 0). Source IRQ 2 is unused
- */
- if (irq0_override && i == 2)
- continue;
-#endif
- putb(&q, 3); /* entry type = I/O interrupt */
- putb(&q, 0); /* interrupt type = vectored interrupt */
- putb(&q, 0); /* flags: po=0, el=0 */
- putb(&q, 0);
- putb(&q, 0); /* source bus ID = ISA */
- putb(&q, i); /* source bus IRQ */
- putb(&q, ioapic_id); /* dest I/O APIC ID */
-#ifdef BX_QEMU
- if (irq0_override && i == 0)
- putb(&q, 2); /* dest I/O APIC interrupt in */
- else
-#endif
- putb(&q, i); /* dest I/O APIC interrupt in */
- }
- /* patch length */
- len = q - mp_config_table;
- mp_config_table[4] = len;
- mp_config_table[5] = len >> 8;
-
- mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
-
- mp_config_table_size = q - mp_config_table;
-
-#ifndef BX_USE_EBDA_TABLES
- bios_table_cur_addr += mp_config_table_size;
-#endif
-
- /* floating pointer structure */
-#ifdef BX_USE_EBDA_TABLES
- ebda_cur_addr = align(ebda_cur_addr, 16);
- float_pointer_struct = (uint8_t *)ebda_cur_addr;
-#else
- bios_table_cur_addr = align(bios_table_cur_addr, 16);
- float_pointer_struct = (uint8_t *)bios_table_cur_addr;
-#endif
- q = float_pointer_struct;
- putstr(&q, "_MP_");
- /* pointer to MP config table */
- putle32(&q, (unsigned long)mp_config_table);
-
- putb(&q, 1); /* length in 16 byte units */
- putb(&q, 4); /* MP spec revision */
- putb(&q, 0); /* checksum (patched later) */
- putb(&q, 0); /* MP feature byte 1 */
-
- putb(&q, 0);
- putb(&q, 0);
- putb(&q, 0);
- putb(&q, 0);
- float_pointer_struct[10] =
- -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
-#ifdef BX_USE_EBDA_TABLES
- ebda_cur_addr += (q - float_pointer_struct);
-#else
- bios_table_cur_addr += (q - float_pointer_struct);
-#endif
- BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n",
- (unsigned long)float_pointer_struct,
- (unsigned long)mp_config_table,
- mp_config_table_size);
-}
-
-/****************************************************/
-/* ACPI tables init */
-
-/* Table structure from Linux kernel (the ACPI tables are under the
- BSD license) */
-
-/*
- * All tables must be byte-packed to match the ACPI specification, since
- * the tables are provided by the system BIOS.
- */
-
-#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
- uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
- uint32_t length; /* Length of table, in bytes, including header */\
- uint8_t revision; /* ACPI Specification minor version # */\
- uint8_t checksum; /* To make sum of entire table == 0 */\
- uint8_t oem_id [6]; /* OEM identification */\
- uint8_t oem_table_id [8]; /* OEM table identification */\
- uint32_t oem_revision; /* OEM revision number */\
- uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
- uint32_t asl_compiler_revision; /* ASL compiler revision number */
-
-
-struct acpi_table_header /* ACPI common table header */
-{
- ACPI_TABLE_HEADER_DEF
-} __attribute__((__packed__));
-
-struct rsdp_descriptor /* Root System Descriptor Pointer */
-{
- uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */
- uint8_t checksum; /* To make sum of struct == 0 */
- uint8_t oem_id [6]; /* OEM identification */
- uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
- uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
- uint32_t length; /* XSDT Length in bytes including hdr */
- uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
- uint8_t extended_checksum; /* Checksum of entire table */
- uint8_t reserved [3]; /* Reserved field must be 0 */
-} __attribute__((__packed__));
-
-#define MAX_RSDT_ENTRIES 100
-
-/*
- * ACPI 1.0 Root System Description Table (RSDT)
- */
-struct rsdt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t table_offset_entry [MAX_RSDT_ENTRIES]; /* Array of pointers to other */
- /* ACPI tables */
-} __attribute__((__packed__));
-
-/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
- */
-struct facs_descriptor_rev1
-{
- uint8_t signature[4]; /* ACPI Signature */
- uint32_t length; /* Length of structure, in bytes */
- uint32_t hardware_signature; /* Hardware configuration signature */
- uint32_t firmware_waking_vector; /* ACPI OS waking vector */
- uint32_t global_lock; /* Global Lock */
- uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */
- uint32_t reserved1 : 31; /* Must be 0 */
- uint8_t resverved3 [40]; /* Reserved - must be zero */
-} __attribute__((__packed__));
-
-
-/*
- * ACPI 1.0 Fixed ACPI Description Table (FADT)
- */
-struct fadt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t firmware_ctrl; /* Physical address of FACS */
- uint32_t dsdt; /* Physical address of DSDT */
- uint8_t model; /* System Interrupt Model */
- uint8_t reserved1; /* Reserved */
- uint16_t sci_int; /* System vector of SCI interrupt */
- uint32_t smi_cmd; /* Port address of SMI command port */
- uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
- uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
- uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
- uint8_t reserved2; /* Reserved - must be zero */
- uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
- uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
- uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
- uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
- uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
- uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
- uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
- uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
- uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
- uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
- uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
- uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
- uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
- uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
- uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
- uint8_t reserved3; /* Reserved */
- uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
- uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
- uint16_t flush_size; /* Size of area read to flush caches */
- uint16_t flush_stride; /* Stride used in flushing caches */
- uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
- uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
- uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
- uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
- uint8_t century; /* Index to century in RTC CMOS RAM */
- uint8_t reserved4; /* Reserved */
- uint8_t reserved4a; /* Reserved */
- uint8_t reserved4b; /* Reserved */
-#if 0
- uint32_t wb_invd : 1; /* The wbinvd instruction works properly */
- uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
- uint32_t proc_c1 : 1; /* All processors support C1 state */
- uint32_t plvl2_up : 1; /* C2 state works on MP system */
- uint32_t pwr_button : 1; /* Power button is handled as a generic feature */
- uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
- uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
- uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
- uint32_t reserved5 : 23; /* Reserved - must be zero */
-#else
- uint32_t flags;
-#endif
-} __attribute__((__packed__));
-
-/*
- * MADT values and structures
- */
-
-/* Values for MADT PCATCompat */
-
-#define DUAL_PIC 0
-#define MULTIPLE_APIC 1
-
-
-/* Master MADT */
-
-struct multiple_apic_table
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t local_apic_address; /* Physical address of local APIC */
-#if 0
- uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */
- uint32_t reserved1 : 31;
-#else
- uint32_t flags;
-#endif
-} __attribute__((__packed__));
-
-
-/* Values for Type in APIC sub-headers */
-
-#define APIC_PROCESSOR 0
-#define APIC_IO 1
-#define APIC_XRUPT_OVERRIDE 2
-#define APIC_NMI 3
-#define APIC_LOCAL_NMI 4
-#define APIC_ADDRESS_OVERRIDE 5
-#define APIC_IO_SAPIC 6
-#define APIC_LOCAL_SAPIC 7
-#define APIC_XRUPT_SOURCE 8
-#define APIC_RESERVED 9 /* 9 and greater are reserved */
-
-#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
- uint8_t type; \
- uint8_t length;
-
-/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
- */
-/* Sub-structures for MADT */
-
-struct madt_processor_apic
-{
- ACPI_SUB_HEADER_DEF
- uint8_t processor_id; /* ACPI processor id */
- uint8_t local_apic_id; /* Processor's local APIC id */
-#if 0
- uint32_t processor_enabled: 1; /* Processor is usable if set */
- uint32_t reserved2 : 31; /* Reserved, must be zero */
-#else
- uint32_t flags;
-#endif
-} __attribute__((__packed__));
-
-/*
- * SRAT (NUMA topology description) table
- */
-
-#define SRAT_PROCESSOR 0
-#define SRAT_MEMORY 1
-
-struct system_resource_affinity_table
-{
- ACPI_TABLE_HEADER_DEF
- uint32_t reserved1;
- uint32_t reserved2[2];
-};
-
-struct srat_processor_affinity
-{
- ACPI_SUB_HEADER_DEF
- uint8_t proximity_lo;
- uint8_t local_apic_id;
- uint32_t flags;
- uint8_t local_sapic_eid;
- uint8_t proximity_hi[3];
- uint32_t reserved;
-};
-
-struct srat_memory_affinity
-{
- ACPI_SUB_HEADER_DEF
- uint8_t proximity[4];
- uint16_t reserved1;
- uint32_t base_addr_low,base_addr_high;
- uint32_t length_low,length_high;
- uint32_t reserved2;
- uint32_t flags;
- uint32_t reserved3[2];
-};
-
-#ifdef BX_QEMU
-/*
- * * ACPI 2.0 Generic Address Space definition.
- * */
-struct acpi_20_generic_address {
- uint8_t address_space_id;
- uint8_t register_bit_width;
- uint8_t register_bit_offset;
- uint8_t reserved;
- uint64_t address;
-} __attribute__((__packed__));
-
-/*
- * HPET Description Table
- */
-struct acpi_20_hpet {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t timer_block_id;
- struct acpi_20_generic_address addr;
- uint8_t hpet_number;
- uint16_t min_tick;
- uint8_t page_protect;
-} __attribute__((__packed__));
-#define ACPI_HPET_ADDRESS 0xFED00000UL
-#endif
-
-struct madt_io_apic
-{
- ACPI_SUB_HEADER_DEF
- uint8_t io_apic_id; /* I/O APIC ID */
- uint8_t reserved; /* Reserved - must be zero */
- uint32_t address; /* APIC physical address */
- uint32_t interrupt; /* Global system interrupt where INTI
- * lines start */
-} __attribute__((__packed__));
-
-#ifdef BX_QEMU
-struct madt_int_override
-{
- ACPI_SUB_HEADER_DEF
- uint8_t bus; /* Identifies ISA Bus */
- uint8_t source; /* Bus-relative interrupt source */
- uint32_t gsi; /* GSI that source will signal */
- uint16_t flags; /* MPS INTI flags */
-} __attribute__((__packed__));
-#endif
-
-#include "acpi-dsdt.hex"
-#include "acpi-ssdt.hex"
-
-static inline uint16_t cpu_to_le16(uint16_t x)
-{
- return x;
-}
-
-static inline uint32_t cpu_to_le32(uint32_t x)
-{
- return x;
-}
-
-static int acpi_checksum(const uint8_t *data, int len)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < len; i++)
- sum += data[i];
- return (-sum) & 0xff;
-}
-
-static void acpi_build_table_header(struct acpi_table_header *h,
- char *sig, int len, uint8_t rev)
-{
- memcpy(h->signature, sig, 4);
- h->length = cpu_to_le32(len);
- h->revision = rev;
-#ifdef BX_QEMU
- memcpy(h->oem_id, "QEMU ", 6);
- memcpy(h->oem_table_id, "QEMU", 4);
-#else
- memcpy(h->oem_id, "BOCHS ", 6);
- memcpy(h->oem_table_id, "BXPC", 4);
-#endif
- memcpy(h->oem_table_id + 4, sig, 4);
- h->oem_revision = cpu_to_le32(1);
-#ifdef BX_QEMU
- memcpy(h->asl_compiler_id, "QEMU", 4);
-#else
- memcpy(h->asl_compiler_id, "BXPC", 4);
-#endif
- h->asl_compiler_revision = cpu_to_le32(1);
- h->checksum = acpi_checksum((void *)h, len);
-}
-
-static void acpi_build_srat_memory(struct srat_memory_affinity *numamem,
- uint64_t base, uint64_t len, int node, int enabled)
-{
- numamem->type = SRAT_MEMORY;
- numamem->length = sizeof(*numamem);
- memset (numamem->proximity, 0 ,4);
- numamem->proximity[0] = node;
- numamem->flags = cpu_to_le32(!!enabled);
- numamem->base_addr_low = base & 0xFFFFFFFF;
- numamem->base_addr_high = base >> 32;
- numamem->length_low = len & 0xFFFFFFFF;
- numamem->length_high = len >> 32;
- return;
-}
-
-/* base_addr must be a multiple of 4KB */
-void acpi_bios_init(void)
-{
- struct rsdp_descriptor *rsdp;
- struct rsdt_descriptor_rev1 *rsdt;
- struct fadt_descriptor_rev1 *fadt;
- struct facs_descriptor_rev1 *facs;
- struct multiple_apic_table *madt;
- uint8_t *dsdt, *ssdt;
-#ifdef BX_QEMU
- struct system_resource_affinity_table *srat;
- struct acpi_20_hpet *hpet;
- uint32_t hpet_addr;
-#endif
- uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
- uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size, madt_end, rsdt_end;
- uint32_t srat_addr,srat_size;
- uint16_t i, external_tables;
- int nb_numa_nodes;
- int nb_rsdt_entries = 0;
-
- /* reserve memory space for tables */
-#ifdef BX_USE_EBDA_TABLES
- ebda_cur_addr = align(ebda_cur_addr, 16);
- rsdp = (void *)(ebda_cur_addr);
- ebda_cur_addr += sizeof(*rsdp);
-#else
- bios_table_cur_addr = align(bios_table_cur_addr, 16);
- rsdp = (void *)(bios_table_cur_addr);
- bios_table_cur_addr += sizeof(*rsdp);
-#endif
-
-#ifdef BX_QEMU
- external_tables = acpi_additional_tables();
-#else
- external_tables = 0;
-#endif
-
- addr = base_addr = ram_size - ACPI_DATA_SIZE;
- rsdt_addr = addr;
- rsdt = (void *)(addr);
- rsdt_size = sizeof(*rsdt);
- addr += rsdt_size;
-
- fadt_addr = addr;
- fadt = (void *)(addr);
- addr += sizeof(*fadt);
-
- /* XXX: FACS should be in RAM */
- addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
- facs_addr = addr;
- facs = (void *)(addr);
- addr += sizeof(*facs);
-
- dsdt_addr = addr;
- dsdt = (void *)(addr);
- addr += sizeof(DSDTCode);
-
- ssdt_addr = addr;
- ssdt = (void *)(addr);
- addr += sizeof(SSDTCode);
-
-#ifdef BX_QEMU
- qemu_cfg_select(QEMU_CFG_NUMA);
- nb_numa_nodes = qemu_cfg_get64();
-#else
- nb_numa_nodes = 0;
-#endif
- if (nb_numa_nodes > 0) {
- addr = (addr + 7) & ~7;
- srat_addr = addr;
- srat_size = sizeof(*srat) +
- sizeof(struct srat_processor_affinity) * smp_cpus +
- sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
- srat = (void *)(addr);
- addr += srat_size;
- } else {
- srat_addr = addr;
- srat = (void*)(addr);
- srat_size = 0;
- }
-
- addr = (addr + 7) & ~7;
- madt_addr = addr;
- madt_size = sizeof(*madt) +
- sizeof(struct madt_processor_apic) * MAX_CPUS +
-#ifdef BX_QEMU
- sizeof(struct madt_io_apic) + sizeof(struct madt_int_override) * MAX_INT_OVERRIDES;
-#else
- sizeof(struct madt_io_apic);
-#endif
- madt = (void *)(addr);
- addr += madt_size;
-
-#ifdef BX_QEMU
- addr = (addr + 7) & ~7;
- hpet_addr = addr;
- hpet = (void *)(addr);
- addr += sizeof(*hpet);
-#endif
-
- /* RSDP */
- memset(rsdp, 0, sizeof(*rsdp));
- memcpy(rsdp->signature, "RSD PTR ", 8);
-#ifdef BX_QEMU
- memcpy(rsdp->oem_id, "QEMU ", 6);
-#else
- memcpy(rsdp->oem_id, "BOCHS ", 6);
-#endif
- rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
- rsdp->checksum = acpi_checksum((void *)rsdp, 20);
-
- /* FADT */
- memset(fadt, 0, sizeof(*fadt));
- fadt->firmware_ctrl = cpu_to_le32(facs_addr);
- fadt->dsdt = cpu_to_le32(dsdt_addr);
- fadt->model = 1;
- fadt->reserved1 = 0;
- fadt->sci_int = cpu_to_le16(pm_sci_int);
- fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
- fadt->acpi_enable = 0xf1;
- fadt->acpi_disable = 0xf0;
- fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
- fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
- fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
- fadt->pm1_evt_len = 4;
- fadt->pm1_cnt_len = 2;
- fadt->pm_tmr_len = 4;
- fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
- fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
- fadt->gpe0_blk = cpu_to_le32(0xafe0);
- fadt->gpe0_blk_len = 4;
- /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
- acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
- sizeof(*fadt), 1);
-
- /* FACS */
- memset(facs, 0, sizeof(*facs));
- memcpy(facs->signature, "FACS", 4);
- facs->length = cpu_to_le32(sizeof(*facs));
- BX_INFO("Firmware waking vector %p\n", &facs->firmware_waking_vector);
-
- /* DSDT */
- memcpy(dsdt, DSDTCode, sizeof(DSDTCode));
-
- /* SSDT */
- memcpy(ssdt, SSDTCode, sizeof(SSDTCode));
-
- /* MADT */
- {
- struct madt_processor_apic *apic;
- struct madt_io_apic *io_apic;
-#ifdef BX_QEMU
- struct madt_int_override *int_override;
-#endif
-
- memset(madt, 0, madt_size);
- madt->local_apic_address = cpu_to_le32(0xfee00000);
- madt->flags = cpu_to_le32(1);
- *(uint32_t*)APIC_MADT_PTR = apic = (void *)(madt + 1);
- for(i=0;i<MAX_CPUS;i++) {
- apic->type = APIC_PROCESSOR;
- apic->length = sizeof(*apic);
- apic->processor_id = i;
- apic->local_apic_id = i;
- if (i < smp_cpus)
- apic->flags = cpu_to_le32(1);
- else
- apic->flags = 0;
- apic++;
- }
- io_apic = (void *)apic;
- io_apic->type = APIC_IO;
- io_apic->length = sizeof(*io_apic);
- io_apic->io_apic_id = smp_cpus;
- io_apic->address = cpu_to_le32(0xfec00000);
- io_apic->interrupt = cpu_to_le32(0);
- io_apic++;
- int_override = (struct madt_int_override*)(io_apic);
-#ifdef BX_QEMU
- if (irq0_override) {
- memset(int_override, 0, sizeof(*int_override));
- int_override->type = APIC_XRUPT_OVERRIDE;
- int_override->length = sizeof(*int_override);
- int_override->source = 0;
- int_override->gsi = 2;
- int_override->flags = 0; /* conforms to bus specifications */
- int_override++;
- }
-#endif
- for (i = 0; i < 16; i++) {
- if (PCI_ISA_IRQ_MASK & (1U << i)) {
- memset(int_override, 0, sizeof(*int_override));
- int_override->type = APIC_XRUPT_OVERRIDE;
- int_override->length = sizeof(*int_override);
- int_override->source = i;
- int_override->gsi = i;
- int_override->flags = 0xd; /* active high, level triggered */
- } else {
- /* No need for a INT source override structure. */
- continue;
- }
- int_override++;
- }
- madt_end = (uint32_t)int_override;
- madt_size = madt_end - madt_addr;
- acpi_build_table_header((struct acpi_table_header *)madt,
- "APIC", madt_size, 1);
- }
-
- memset(rsdt, 0, rsdt_size);
-#ifdef BX_QEMU
- /* SRAT */
- if (nb_numa_nodes > 0) {
- struct srat_processor_affinity *core;
- struct srat_memory_affinity *numamem;
- int slots;
- uint64_t mem_len, mem_base, next_base = 0, curnode;
-
- qemu_cfg_select(QEMU_CFG_NUMA);
- qemu_cfg_get64();
- memset (srat, 0 , srat_size);
- srat->reserved1=1;
-
- core = (void*)(srat + 1);
- for (i = 0; i < smp_cpus; ++i) {
- core->type = SRAT_PROCESSOR;
- core->length = sizeof(*core);
- core->local_apic_id = i;
- curnode = qemu_cfg_get64();
- core->proximity_lo = curnode;
- memset (core->proximity_hi, 0, 3);
- core->local_sapic_eid = 0;
- if (i < smp_cpus)
- core->flags = cpu_to_le32(1);
- else
- core->flags = 0;
- core++;
- }
-
- /* the memory map is a bit tricky, it contains at least one hole
- * from 640k-1M and possibly another one from 3.5G-4G.
- */
- numamem = (void*)core; slots = 0;
- acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
- next_base = 1024 * 1024; numamem++;slots++;
- for (i = 1; i < nb_numa_nodes + 1; ++i) {
- mem_base = next_base;
- mem_len = qemu_cfg_get64();
- if (i == 1) mem_len -= 1024 * 1024;
- next_base = mem_base + mem_len;
-
- /* Cut out the PCI hole */
- if (mem_base <= ram_size && next_base > ram_size) {
- mem_len -= next_base - ram_size;
- if (mem_len > 0) {
- acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
- numamem++; slots++;
- }
- mem_base = 1ULL << 32;
- mem_len = next_base - ram_size;
- next_base += (1ULL << 32) - ram_size;
- }
- acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
- numamem++; slots++;
- }
- for (; slots < nb_numa_nodes + 2; slots++) {
- acpi_build_srat_memory(numamem, 0, 0, 0, 0);
- numamem++;
- }
-
- acpi_build_table_header((struct acpi_table_header *)srat,
- "SRAT", srat_size, 1);
- }
-
- /* HPET */
- memset(hpet, 0, sizeof(*hpet));
- /* Note timer_block_id value must be kept in sync with value advertised by
- * emulated hpet
- */
- hpet->timer_block_id = cpu_to_le32(0x8086a201);
- hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
- acpi_build_table_header((struct acpi_table_header *)hpet,
- "HPET", sizeof(*hpet), 1);
-
-#endif
-
- /* RSDT */
- rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(fadt_addr);
- /* On real hardware the SSDT seems to come before the MADT (APIC) */
- rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(ssdt_addr);
- rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(madt_addr);
-#ifdef BX_QEMU
- rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(hpet_addr);
- if (nb_numa_nodes > 0)
- rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(srat_addr);
- acpi_additional_tables(); /* resets cfg to required entry */
- for(i = 0; i < external_tables; i++) {
- uint16_t len;
- if(acpi_load_table(i, addr, &len) < 0)
- BX_PANIC("Failed to load ACPI table from QEMU\n");
- rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(addr);
- addr += len;
- if ((addr >= ram_size) || (nb_rsdt_entries > MAX_RSDT_ENTRIES))
- BX_PANIC("ACPI table overflow\n");
- }
-#endif
- rsdt_end = (uint32_t)(&rsdt->table_offset_entry[nb_rsdt_entries]);
- rsdt_size = rsdt_end - rsdt_addr;
- acpi_build_table_header((struct acpi_table_header *)rsdt, "RSDT",
- rsdt_size, 1);
-
- acpi_tables_size = addr - base_addr;
-
- BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
- (unsigned long)rsdp,
- (unsigned long)rsdt, acpi_tables_size);
-
-}
-
-/* SMBIOS entry point -- must be written to a 16-bit aligned address
- between 0xf0000 and 0xfffff.
- */
-struct smbios_entry_point {
- char anchor_string[4];
- uint8_t checksum;
- uint8_t length;
- uint8_t smbios_major_version;
- uint8_t smbios_minor_version;
- uint16_t max_structure_size;
- uint8_t entry_point_revision;
- uint8_t formatted_area[5];
- char intermediate_anchor_string[5];
- uint8_t intermediate_checksum;
- uint16_t structure_table_length;
- uint32_t structure_table_address;
- uint16_t number_of_structures;
- uint8_t smbios_bcd_revision;
-} __attribute__((__packed__));
-
-/* This goes at the beginning of every SMBIOS structure. */
-struct smbios_structure_header {
- uint8_t type;
- uint8_t length;
- uint16_t handle;
-} __attribute__((__packed__));
-
-/* SMBIOS type 0 - BIOS Information */
-struct smbios_type_0 {
- struct smbios_structure_header header;
- uint8_t vendor_str;
- uint8_t bios_version_str;
- uint16_t bios_starting_address_segment;
- uint8_t bios_release_date_str;
- uint8_t bios_rom_size;
- uint8_t bios_characteristics[8];
- uint8_t bios_characteristics_extension_bytes[2];
- uint8_t system_bios_major_release;
- uint8_t system_bios_minor_release;
- uint8_t embedded_controller_major_release;
- uint8_t embedded_controller_minor_release;
-} __attribute__((__packed__));
-
-/* SMBIOS type 1 - System Information */
-struct smbios_type_1 {
- struct smbios_structure_header header;
- uint8_t manufacturer_str;
- uint8_t product_name_str;
- uint8_t version_str;
- uint8_t serial_number_str;
- uint8_t uuid[16];
- uint8_t wake_up_type;
- uint8_t sku_number_str;
- uint8_t family_str;
-} __attribute__((__packed__));
-
-/* SMBIOS type 3 - System Enclosure (v2.3) */
-struct smbios_type_3 {
- struct smbios_structure_header header;
- uint8_t manufacturer_str;
- uint8_t type;
- uint8_t version_str;
- uint8_t serial_number_str;
- uint8_t asset_tag_number_str;
- uint8_t boot_up_state;
- uint8_t power_supply_state;
- uint8_t thermal_state;
- uint8_t security_status;
- uint32_t oem_defined;
- uint8_t height;
- uint8_t number_of_power_cords;
- uint8_t contained_element_count;
- // contained elements follow
-} __attribute__((__packed__));
-
-/* SMBIOS type 4 - Processor Information (v2.0) */
-struct smbios_type_4 {
- struct smbios_structure_header header;
- uint8_t socket_designation_str;
- uint8_t processor_type;
- uint8_t processor_family;
- uint8_t processor_manufacturer_str;
- uint32_t processor_id[2];
- uint8_t processor_version_str;
- uint8_t voltage;
- uint16_t external_clock;
- uint16_t max_speed;
- uint16_t current_speed;
- uint8_t status;
- uint8_t processor_upgrade;
- uint16_t l1_cache_handle;
- uint16_t l2_cache_handle;
- uint16_t l3_cache_handle;
-} __attribute__((__packed__));
-
-/* SMBIOS type 16 - Physical Memory Array
- * Associated with one type 17 (Memory Device).
- */
-struct smbios_type_16 {
- struct smbios_structure_header header;
- uint8_t location;
- uint8_t use;
- uint8_t error_correction;
- uint32_t maximum_capacity;
- uint16_t memory_error_information_handle;
- uint16_t number_of_memory_devices;
-} __attribute__((__packed__));
-
-/* SMBIOS type 17 - Memory Device
- * Associated with one type 19
- */
-struct smbios_type_17 {
- struct smbios_structure_header header;
- uint16_t physical_memory_array_handle;
- uint16_t memory_error_information_handle;
- uint16_t total_width;
- uint16_t data_width;
- uint16_t size;
- uint8_t form_factor;
- uint8_t device_set;
- uint8_t device_locator_str;
- uint8_t bank_locator_str;
- uint8_t memory_type;
- uint16_t type_detail;
-} __attribute__((__packed__));
-
-/* SMBIOS type 19 - Memory Array Mapped Address */
-struct smbios_type_19 {
- struct smbios_structure_header header;
- uint32_t starting_address;
- uint32_t ending_address;
- uint16_t memory_array_handle;
- uint8_t partition_width;
-} __attribute__((__packed__));
-
-/* SMBIOS type 20 - Memory Device Mapped Address */
-struct smbios_type_20 {
- struct smbios_structure_header header;
- uint32_t starting_address;
- uint32_t ending_address;
- uint16_t memory_device_handle;
- uint16_t memory_array_mapped_address_handle;
- uint8_t partition_row_position;
- uint8_t interleave_position;
- uint8_t interleaved_data_depth;
-} __attribute__((__packed__));
-
-/* SMBIOS type 32 - System Boot Information */
-struct smbios_type_32 {
- struct smbios_structure_header header;
- uint8_t reserved[6];
- uint8_t boot_status;
-} __attribute__((__packed__));
-
-/* SMBIOS type 127 -- End-of-table */
-struct smbios_type_127 {
- struct smbios_structure_header header;
-} __attribute__((__packed__));
-
-static void
-smbios_entry_point_init(void *start,
- uint16_t max_structure_size,
- uint16_t structure_table_length,
- uint32_t structure_table_address,
- uint16_t number_of_structures)
-{
- uint8_t sum;
- int i;
- struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
-
- memcpy(ep->anchor_string, "_SM_", 4);
- ep->length = 0x1f;
- ep->smbios_major_version = 2;
- ep->smbios_minor_version = 4;
- ep->max_structure_size = max_structure_size;
- ep->entry_point_revision = 0;
- memset(ep->formatted_area, 0, 5);
- memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
-
- ep->structure_table_length = structure_table_length;
- ep->structure_table_address = structure_table_address;
- ep->number_of_structures = number_of_structures;
- ep->smbios_bcd_revision = 0x24;
-
- ep->checksum = 0;
- ep->intermediate_checksum = 0;
-
- sum = 0;
- for (i = 0; i < 0x10; i++)
- sum += ((int8_t *)start)[i];
- ep->checksum = -sum;
-
- sum = 0;
- for (i = 0x10; i < ep->length; i++)
- sum += ((int8_t *)start)[i];
- ep->intermediate_checksum = -sum;
- }
-
-struct smbios_header {
- uint16_t length;
- uint8_t type;
-} __attribute__((__packed__));
-
-struct smbios_field {
- struct smbios_header header;
- uint8_t type;
- uint16_t offset;
- uint8_t data[];
-} __attribute__((__packed__));
-
-struct smbios_table {
- struct smbios_header header;
- uint8_t data[];
-} __attribute__((__packed__));
-
-#define SMBIOS_FIELD_ENTRY 0
-#define SMBIOS_TABLE_ENTRY 1
-
-static size_t
-smbios_load_field(int type, size_t offset, void *addr)
-{
-#ifdef BX_QEMU
- int i;
-
- for (i = smbios_entries(); i > 0; i--) {
- struct smbios_field field;
-
- qemu_cfg_read((uint8_t *)&field, sizeof(struct smbios_header));
- field.header.length -= sizeof(struct smbios_header);
-
- if (field.header.type != SMBIOS_FIELD_ENTRY) {
- while (field.header.length--)
- inb(QEMU_CFG_DATA_PORT);
- continue;
- }
-
- qemu_cfg_read((uint8_t *)&field.type,
- sizeof(field) - sizeof(struct smbios_header));
- field.header.length -= sizeof(field) - sizeof(struct smbios_header);
-
- if (field.type != type || field.offset != offset) {
- while (field.header.length--)
- inb(QEMU_CFG_DATA_PORT);
- continue;
- }
-
- qemu_cfg_read(addr, field.header.length);
- return (size_t)field.header.length;
- }
-#endif
- return 0;
-}
-
-#define load_str_field_with_default(type, field, def) do { \
- size = smbios_load_field(type, offsetof(struct smbios_type_##type, \
- field), end); \
- if (size > 0) { \
- end += size; \
- } else { \
- memcpy(end, def, sizeof(def)); \
- end += sizeof(def); \
- } \
- p->field = ++str_index; \
-} while (0)
-
-#define load_str_field_or_skip(type, field) do { \
- size = smbios_load_field(type, offsetof(struct smbios_type_##type, \
- field), end); \
- if (size > 0) { \
- end += size; \
- p->field = ++str_index; \
- } else { \
- p->field = 0; \
- } \
-} while (0)
-
-/* Type 0 -- BIOS Information */
-#define RELEASE_DATE_STR "01/01/2007"
-static void *
-smbios_init_type_0(void *start)
-{
- struct smbios_type_0 *p = (struct smbios_type_0 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_0);
- size_t size;
- int str_index = 0;
-
- p->header.type = 0;
- p->header.length = sizeof(struct smbios_type_0);
- p->header.handle = 0;
-
- load_str_field_with_default(0, vendor_str, BX_APPNAME);
- load_str_field_with_default(0, bios_version_str, BX_APPNAME);
-
- p->bios_starting_address_segment = 0xe800;
-
- load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
-
- p->bios_rom_size = 0; /* FIXME */
-
- memset(p->bios_characteristics, 0, 8);
- p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
- p->bios_characteristics_extension_bytes[0] = 0;
- p->bios_characteristics_extension_bytes[1] = 0;
-
- if (!smbios_load_field(0, offsetof(struct smbios_type_0,
- system_bios_major_release),
- &p->system_bios_major_release))
- p->system_bios_major_release = 1;
-
- if (!smbios_load_field(0, offsetof(struct smbios_type_0,
- system_bios_minor_release),
- &p->system_bios_minor_release))
- p->system_bios_minor_release = 0;
-
- p->embedded_controller_major_release = 0xff;
- p->embedded_controller_minor_release = 0xff;
-
- *end = 0;
- end++;
-
- return end;
-}
-
-/* Type 1 -- System Information */
-static void *
-smbios_init_type_1(void *start)
-{
- struct smbios_type_1 *p = (struct smbios_type_1 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_1);
- size_t size;
- int str_index = 0;
-
- p->header.type = 1;
- p->header.length = sizeof(struct smbios_type_1);
- p->header.handle = 0x100;
-
- load_str_field_or_skip(1, manufacturer_str);
- load_str_field_or_skip(1, product_name_str);
- load_str_field_or_skip(1, version_str);
- load_str_field_or_skip(1, serial_number_str);
-
- size = smbios_load_field(1, offsetof(struct smbios_type_1,
- uuid), &p->uuid);
- if (size == 0)
- memset(p->uuid, 0, 16);
-
- p->wake_up_type = 0x06; /* power switch */
-
- load_str_field_or_skip(1, sku_number_str);
- load_str_field_or_skip(1, family_str);
-
- *end = 0;
- end++;
- if (!str_index) {
- *end = 0;
- end++;
- }
-
- return end;
-}
-
-/* Type 3 -- System Enclosure */
-static void *
-smbios_init_type_3(void *start)
-{
- struct smbios_type_3 *p = (struct smbios_type_3 *)start;
-
- p->header.type = 3;
- p->header.length = sizeof(struct smbios_type_3);
- p->header.handle = 0x300;
-
- p->manufacturer_str = 0;
- p->type = 0x01; /* other */
- p->version_str = 0;
- p->serial_number_str = 0;
- p->asset_tag_number_str = 0;
- p->boot_up_state = 0x03; /* safe */
- p->power_supply_state = 0x03; /* safe */
- p->thermal_state = 0x03; /* safe */
- p->security_status = 0x02; /* unknown */
- p->oem_defined = 0;
- p->height = 0;
- p->number_of_power_cords = 0;
- p->contained_element_count = 0;
-
- start += sizeof(struct smbios_type_3);
- *((uint16_t *)start) = 0;
-
- return start+2;
-}
-
-/* Type 4 -- Processor Information */
-static void *
-smbios_init_type_4(void *start, unsigned int cpu_number)
-{
- struct smbios_type_4 *p = (struct smbios_type_4 *)start;
-
- p->header.type = 4;
- p->header.length = sizeof(struct smbios_type_4);
- p->header.handle = 0x400 + cpu_number;
-
- p->socket_designation_str = 1;
- p->processor_type = 0x03; /* CPU */
- p->processor_family = 0x01; /* other */
- p->processor_manufacturer_str = 0;
-
- p->processor_id[0] = cpuid_signature;
- p->processor_id[1] = cpuid_features;
-
- p->processor_version_str = 0;
- p->voltage = 0;
- p->external_clock = 0;
-
- p->max_speed = 0; /* unknown */
- p->current_speed = 0; /* unknown */
-
- p->status = 0x41; /* socket populated, CPU enabled */
- p->processor_upgrade = 0x01; /* other */
-
- p->l1_cache_handle = 0xffff; /* cache information structure not provided */
- p->l2_cache_handle = 0xffff;
- p->l3_cache_handle = 0xffff;
-
- start += sizeof(struct smbios_type_4);
-
- memcpy((char *)start, "CPU " "\0" "" "\0" "", 7);
- ((char *)start)[4] = cpu_number + '0';
-
- return start+7;
-}
-
-/* Type 16 -- Physical Memory Array */
-static void *
-smbios_init_type_16(void *start, uint32_t memsize, int nr_mem_devs)
-{
- struct smbios_type_16 *p = (struct smbios_type_16*)start;
-
- p->header.type = 16;
- p->header.length = sizeof(struct smbios_type_16);
- p->header.handle = 0x1000;
-
- p->location = 0x01; /* other */
- p->use = 0x03; /* system memory */
- p->error_correction = 0x01; /* other */
- p->maximum_capacity = memsize * 1024;
- p->memory_error_information_handle = 0xfffe; /* none provided */
- p->number_of_memory_devices = nr_mem_devs;
-
- start += sizeof(struct smbios_type_16);
- *((uint16_t *)start) = 0;
-
- return start + 2;
-}
-
-/* Type 17 -- Memory Device */
-static void *
-smbios_init_type_17(void *start, uint32_t memory_size_mb, int instance)
-{
- struct smbios_type_17 *p = (struct smbios_type_17 *)start;
-
- p->header.type = 17;
- p->header.length = sizeof(struct smbios_type_17);
- p->header.handle = 0x1100 + instance;
-
- p->physical_memory_array_handle = 0x1000;
- p->total_width = 64;
- p->data_width = 64;
-/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */
- p->size = memory_size_mb;
- p->form_factor = 0x09; /* DIMM */
- p->device_set = 0;
- p->device_locator_str = 1;
- p->bank_locator_str = 0;
- p->memory_type = 0x07; /* RAM */
- p->type_detail = 0;
-
- start += sizeof(struct smbios_type_17);
- snprintf(start, 8, "DIMM %d", instance);
- start += strlen(start) + 1;
- *((uint8_t *)start) = 0;
-
- return start+1;
-}
-
-/* Type 19 -- Memory Array Mapped Address */
-static void *
-smbios_init_type_19(void *start, uint32_t memory_size_mb, int instance)
-{
- struct smbios_type_19 *p = (struct smbios_type_19 *)start;
-
- p->header.type = 19;
- p->header.length = sizeof(struct smbios_type_19);
- p->header.handle = 0x1300 + instance;
-
- p->starting_address = instance << 24;
- p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
- p->memory_array_handle = 0x1000;
- p->partition_width = 1;
-
- start += sizeof(struct smbios_type_19);
- *((uint16_t *)start) = 0;
-
- return start + 2;
-}
-
-/* Type 20 -- Memory Device Mapped Address */
-static void *
-smbios_init_type_20(void *start, uint32_t memory_size_mb, int instance)
-{
- struct smbios_type_20 *p = (struct smbios_type_20 *)start;
-
- p->header.type = 20;
- p->header.length = sizeof(struct smbios_type_20);
- p->header.handle = 0x1400 + instance;
-
- p->starting_address = instance << 24;
- p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
- p->memory_device_handle = 0x1100 + instance;
- p->memory_array_mapped_address_handle = 0x1300 + instance;
- p->partition_row_position = 1;
- p->interleave_position = 0;
- p->interleaved_data_depth = 0;
-
- start += sizeof(struct smbios_type_20);
-
- *((uint16_t *)start) = 0;
- return start+2;
-}
-
-/* Type 32 -- System Boot Information */
-static void *
-smbios_init_type_32(void *start)
-{
- struct smbios_type_32 *p = (struct smbios_type_32 *)start;
-
- p->header.type = 32;
- p->header.length = sizeof(struct smbios_type_32);
- p->header.handle = 0x2000;
- memset(p->reserved, 0, 6);
- p->boot_status = 0; /* no errors detected */
-
- start += sizeof(struct smbios_type_32);
- *((uint16_t *)start) = 0;
-
- return start+2;
-}
-
-/* Type 127 -- End of Table */
-static void *
-smbios_init_type_127(void *start)
-{
- struct smbios_type_127 *p = (struct smbios_type_127 *)start;
-
- p->header.type = 127;
- p->header.length = sizeof(struct smbios_type_127);
- p->header.handle = 0x7f00;
-
- start += sizeof(struct smbios_type_127);
- *((uint16_t *)start) = 0;
-
- return start + 2;
-}
-
-static int
-smbios_load_external(int type, char **p, unsigned *nr_structs,
- unsigned *max_struct_size)
-{
-#ifdef BX_QEMU
- static uint64_t used_bitmap[4] = { 0 };
- char *start = *p;
- int i;
-
- /* Check if we've already reported these tables */
- if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
- return 1;
-
- /* Don't introduce spurious end markers */
- if (type == 127)
- return 0;
-
- for (i = smbios_entries(); i > 0; i--) {
- struct smbios_table table;
- struct smbios_structure_header *header = (void *)*p;
- int string;
-
- qemu_cfg_read((uint8_t *)&table, sizeof(struct smbios_header));
- table.header.length -= sizeof(struct smbios_header);
-
- if (table.header.type != SMBIOS_TABLE_ENTRY) {
- while (table.header.length--)
- inb(QEMU_CFG_DATA_PORT);
- continue;
- }
-
- qemu_cfg_read((uint8_t *)*p, sizeof(struct smbios_structure_header));
- table.header.length -= sizeof(struct smbios_structure_header);
-
- if (header->type != type) {
- while (table.header.length--)
- inb(QEMU_CFG_DATA_PORT);
- continue;
- }
-
- *p += sizeof(struct smbios_structure_header);
-
- /* Entries end with a double NULL char, if there's a string at
- * the end (length is greater than formatted length), the string
- * terminator provides the first NULL. */
- string = header->length < table.header.length +
- sizeof(struct smbios_structure_header);
-
- /* Read the rest and terminate the entry */
- qemu_cfg_read((uint8_t *)*p, table.header.length);
- *p += table.header.length;
- *((uint8_t*)*p) = 0;
- (*p)++;
- if (!string) {
- *((uint8_t*)*p) = 0;
- (*p)++;
- }
-
- (*nr_structs)++;
- if (*p - (char *)header > *max_struct_size)
- *max_struct_size = *p - (char *)header;
- }
-
- if (start != *p) {
- /* Mark that we've reported on this type */
- used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
- return 1;
- }
-
-#endif /* !BX_QEMU */
- return 0;
-}
-
-void smbios_init(void)
-{
- unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
- char *start, *p, *q;
- int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
- (ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
- int i, nr_mem_devs;
-
-#ifdef BX_USE_EBDA_TABLES
- ebda_cur_addr = align(ebda_cur_addr, 16);
- start = (void *)(ebda_cur_addr);
-#else
- bios_table_cur_addr = align(bios_table_cur_addr, 16);
- start = (void *)(bios_table_cur_addr);
-#endif
-
- p = (char *)start + sizeof(struct smbios_entry_point);
-
-#define add_struct(type, args...) do { \
- if (!smbios_load_external(type, &p, &nr_structs, &max_struct_size)) { \
- q = smbios_init_type_##type(args); \
- nr_structs++; \
- if ((q - p) > max_struct_size) \
- max_struct_size = q - p; \
- p = q; \
- } \
-} while (0)
-
- add_struct(0, p);
- add_struct(1, p);
- add_struct(3, p);
- for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
- add_struct(4, p, cpu_num);
-
- /* Each 'memory device' covers up to 16GB of address space. */
- nr_mem_devs = (memsize + 0x3fff) >> 14;
- add_struct(16, p, memsize, nr_mem_devs);
- for ( i = 0; i < nr_mem_devs; i++ )
- {
- uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
- ? (((memsize-1) & 0x3fff)+1) : 0x4000);
- add_struct(17, p, dev_memsize, i);
- add_struct(19, p, dev_memsize, i);
- add_struct(20, p, dev_memsize, i);
- }
-
- add_struct(32, p);
- /* Add any remaining provided entries before the end marker */
- for (i = 0; i < 256; i++)
- smbios_load_external(i, &p, &nr_structs, &max_struct_size);
- add_struct(127, p);
-
-#undef add_struct
-
- smbios_entry_point_init(
- start, max_struct_size,
- (p - (char *)start) - sizeof(struct smbios_entry_point),
- (uint32_t)(start + sizeof(struct smbios_entry_point)),
- nr_structs);
-
-#ifdef BX_USE_EBDA_TABLES
- ebda_cur_addr += (p - (char *)start);
-#else
- bios_table_cur_addr += (p - (char *)start);
-#endif
-
- BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start);
-}
-
-static uint32_t find_resume_vector(void)
-{
- unsigned long addr, start, end;
-
-#ifdef BX_USE_EBDA_TABLES
- start = align(ebda_cur_addr, 16);
- end = 0xa000 << 4;
-#else
- if (bios_table_cur_addr == 0)
- return 0;
- start = align(bios_table_cur_addr, 16);
- end = bios_table_end_addr;
-#endif
-
- for (addr = start; addr < end; addr += 16) {
- if (!memcmp((void*)addr, "RSD PTR ", 8)) {
- struct rsdp_descriptor *rsdp = (void*)addr;
- struct rsdt_descriptor_rev1 *rsdt = (void*)rsdp->rsdt_physical_address;
- struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[0];
- struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
- return facs->firmware_waking_vector;
- }
- }
-
- return 0;
-}
-
-static void find_440fx(PCIDevice *d)
-{
- uint16_t vendor_id, device_id;
-
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
-
- if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441)
- i440_pcidev = *d;
-}
-
-static void reinit_piix4_pm(PCIDevice *d)
-{
- uint16_t vendor_id, device_id;
-
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
-
- if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3)
- piix4_pm_enable(d);
-}
-
-void rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag)
-{
- BX_INFO("Starting rombios32\n");
- BX_INFO("Shutdown flag %x\n", *shutdown_flag);
-
-#ifdef BX_QEMU
- qemu_cfg_port = qemu_cfg_port_probe();
-#endif
-
- init_smp_msrs();
-
- ram_probe();
-
- cpu_probe();
-
- setup_mtrr();
-
- smp_probe();
-
- find_bios_table_area();
-
- if (*shutdown_flag == 0xfe) {
- /* redirect bios read access to RAM */
- pci_for_each_device(find_440fx);
- bios_lock_shadow_ram(); /* bios is already copied */
- *s3_resume_vector = find_resume_vector();
- if (!*s3_resume_vector) {
- BX_INFO("This is S3 resume but wakeup vector is NULL\n");
- } else {
- BX_INFO("S3 resume vector %p\n", *s3_resume_vector);
- pci_for_each_device(reinit_piix4_pm);
- }
- return;
- }
-
- pci_bios_init();
-
- if (bios_table_cur_addr != 0) {
-
-#ifdef BX_QEMU
- irq0_override_probe();
-#endif
- mptable_init();
-
- smbios_init();
-
- if (acpi_enabled)
- acpi_bios_init();
-
- bios_lock_shadow_ram();
-
- BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr);
- if (bios_table_cur_addr > bios_table_end_addr)
- BX_PANIC("bios_table_end_addr overflow!\n");
-#ifdef BX_USE_EBDA_TABLES
- BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
- if (ebda_cur_addr > 0xA0000)
- BX_PANIC("ebda_cur_addr overflow!\n");
-#endif
- }
-}
diff --git a/kvm/bios/rombios32.ld b/kvm/bios/rombios32.ld
deleted file mode 100644
index 1fc99c38f..000000000
--- a/kvm/bios/rombios32.ld
+++ /dev/null
@@ -1,22 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start);
-SECTIONS
-{
- . = 0x000e0000;
- .text : { *(.text) }
- .rodata : { *(.rodata*) }
- . = ALIGN(64);
- fixup_start = .;
- .fixup : { *(.fixup) }
- fixup_end = .;
- . = ALIGN(4096);
- _end = . ;
- .data 0x700 : AT (_end) { __data_start = .; *(.data); __data_end = .;}
- .bss : { __bss_start = .; *(.bss) *(COMMON); __bss_end = .;}
- /DISCARD/ : { *(.stab)
- *(.stabstr)
- *(.comment)
- *(.note)
- }
-}
diff --git a/kvm/bios/rombios32start.S b/kvm/bios/rombios32start.S
deleted file mode 100644
index c9bc045b9..000000000
--- a/kvm/bios/rombios32start.S
+++ /dev/null
@@ -1,119 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id: rombios32start.S,v 1.3 2006/10/02 06:29:38 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// 32 bit Bochs BIOS init code
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#include "rombios.h"
-
-.globl _start
-.globl smp_ap_boot_code_start
-.globl smp_ap_boot_code_end
-.global smm_relocation_start
-.global smm_relocation_end
-.global smm_code_start
-.global smm_code_end
-
-_start:
- /* clear bss section */
- xor %eax, %eax
- mov $__bss_start, %edi
- mov $__bss_end, %ecx
- sub %edi, %ecx
- rep stosb
-
- /* copy data section */
- mov $_end, %esi
- mov $__data_start, %edi
- mov $__data_end, %ecx
- sub %edi, %ecx
- rep movsb
-
- jmp rombios32_init
-
- .code16
-smp_ap_boot_code_start:
- cli
- xor %ax, %ax
- mov %ax, %ds
-
- mov $SMP_MSR_ADDR, %ebx
-11:
- mov 0(%ebx), %ecx
- test %ecx, %ecx
- jz 12f
- mov 4(%ebx), %eax
- mov 8(%ebx), %edx
- wrmsr
- add $12, %ebx
- jmp 11b
-12:
-
- lock incw smp_cpus
-1:
- hlt
- jmp 1b
-smp_ap_boot_code_end:
-
-/* code to relocate SMBASE to 0xa0000 */
-smm_relocation_start:
- mov $0x38000 + 0x7efc, %ebx
- addr32 mov (%ebx), %al /* revision ID to see if x86_64 or x86 */
- cmp $0x64, %al
- je 1f
- mov $0x38000 + 0x7ef8, %ebx
- jmp 2f
-1:
- mov $0x38000 + 0x7f00, %ebx
-2:
- movl $0xa0000, %eax
- addr32 movl %eax, (%ebx)
- /* indicate to the BIOS that the SMM code was executed */
- mov $0x00, %al
- movw $0xb3, %dx
- outb %al, %dx
- rsm
-smm_relocation_end:
-
-/* minimal SMM code to enable or disable ACPI */
-smm_code_start:
- movw $0xb2, %dx
- inb %dx, %al
- cmp $0xf0, %al
- jne 1f
-
- /* ACPI disable */
- mov $PM_IO_BASE + 0x04, %dx /* PMCNTRL */
- inw %dx, %ax
- andw $~1, %ax
- outw %ax, %dx
-
- jmp 2f
-
-1:
- cmp $0xf1, %al
- jne 2f
-
- /* ACPI enable */
- mov $PM_IO_BASE + 0x04, %dx /* PMCNTRL */
- inw %dx, %ax
- orw $1, %ax
- outw %ax, %dx
-
-2:
- rsm
-smm_code_end:
diff --git a/kvm/bios/usage.cc b/kvm/bios/usage.cc
deleted file mode 100644
index 8db95479c..000000000
--- a/kvm/bios/usage.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id: usage.cc,v 1.4 2003/10/07 01:44:34 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-
-unsigned char bios[65536];
-
- int
-main(int argc, char *argv[])
-{
- int bios_file;
- FILE * org_file;
- unsigned org, last_org, offset;
- int retval;
- unsigned int to_read, index;
- double elements, ratio;
-
- if (argc !=3 ) {
- fprintf(stderr, "Usage: usage bios-file org-file\n");
- exit(1);
- }
-
- bios_file = open(argv[1], O_RDONLY);
- org_file = fopen(argv[2], "r");
-
- if ( (bios_file<0) | (org_file==NULL) ) {
- fprintf(stderr, "problems opening files.\n");
- exit(1);
- }
-
- printf("files opened OK\n");
-
- to_read = 65536;
- index = 0;
- while (to_read > 0) {
- retval = read(bios_file, &bios[index], to_read);
- if (retval <= 0) {
- fprintf(stderr, "problem reading bios file\n");
- exit(1);
- }
- to_read -= retval;
- index += retval;
- }
- printf("bios file read in OK\n");
-
- last_org = 0;
-
- while (1) {
- retval = fscanf(org_file, "0x%x\n", &org);
- if (retval <= 0) break;
- printf("%04x .. %04x ", last_org, org-1);
- for (offset=org-1; offset>last_org; offset--) {
- if (bios[offset] != 0) break;
- }
- if (offset > last_org) {
- elements = (1.0 + double(offset) - double(last_org));
- }
- else {
- if (bios[last_org] == 0)
- elements = 0.0;
- else
- elements = 1.0;
- }
-
- ratio = elements / (double(org) - double(last_org));
- ratio *= 100.0;
- printf("%6.2lf\n", ratio);
- last_org = org;
- }
-}
diff --git a/kvm/bios/vapic.S b/kvm/bios/vapic.S
deleted file mode 100644
index cf2a474d5..000000000
--- a/kvm/bios/vapic.S
+++ /dev/null
@@ -1,294 +0,0 @@
- .text
- .code32
- .align 4096
-
-vapic_size = 2*4096
-
-.macro fixup delta=-4
-777:
- .pushsection .fixup, "a"
- .long 777b + \delta - vapic_base
- .popsection
-.endm
-
-.macro reenable_vtpr
- out %al, $0x7e
-.endm
-
-vapic_base:
- .ascii "kvm aPiC"
-
- /* relocation data */
- .long vapic_base ; fixup
- .long fixup_start ; fixup
- .long fixup_end ; fixup
-
- .long vapic ; fixup
- .long vapic_size
-vcpu_shift:
- .long 0
-real_tpr:
- .long 0
- .long up_set_tpr ; fixup
- .long up_set_tpr_eax ; fixup
- .long up_get_tpr_eax ; fixup
- .long up_get_tpr_ecx ; fixup
- .long up_get_tpr_edx ; fixup
- .long up_get_tpr_ebx ; fixup
- .long 0 /* esp. won't work. */
- .long up_get_tpr_ebp ; fixup
- .long up_get_tpr_esi ; fixup
- .long up_get_tpr_edi ; fixup
- .long up_get_tpr_stack ; fixup
- .long mp_set_tpr ; fixup
- .long mp_set_tpr_eax ; fixup
- .long mp_get_tpr_eax ; fixup
- .long mp_get_tpr_ecx ; fixup
- .long mp_get_tpr_edx ; fixup
- .long mp_get_tpr_ebx ; fixup
- .long 0 /* esp. won't work. */
- .long mp_get_tpr_ebp ; fixup
- .long mp_get_tpr_esi ; fixup
- .long mp_get_tpr_edi ; fixup
- .long mp_get_tpr_stack ; fixup
-
-.macro kvm_hypercall
- .byte 0x0f, 0x01, 0xc1
-.endm
-
-kvm_hypercall_vapic_poll_irq = 1
-
-pcr_cpu = 0x51
-
-.align 64
-
-mp_get_tpr_eax:
- pushf
- cli
- reenable_vtpr
- push %ecx
-
- fs/movzbl pcr_cpu, %eax
-
- mov vcpu_shift, %ecx ; fixup
- shl %cl, %eax
- testb $1, vapic+4(%eax) ; fixup delta=-5
- jz mp_get_tpr_bad
- movzbl vapic(%eax), %eax ; fixup
-
-mp_get_tpr_out:
- pop %ecx
- popf
- ret
-
-mp_get_tpr_bad:
- mov real_tpr, %eax ; fixup
- mov (%eax), %eax
- jmp mp_get_tpr_out
-
-mp_get_tpr_ebx:
- mov %eax, %ebx
- call mp_get_tpr_eax
- xchg %eax, %ebx
- ret
-
-mp_get_tpr_ecx:
- mov %eax, %ecx
- call mp_get_tpr_eax
- xchg %eax, %ecx
- ret
-
-mp_get_tpr_edx:
- mov %eax, %edx
- call mp_get_tpr_eax
- xchg %eax, %edx
- ret
-
-mp_get_tpr_esi:
- mov %eax, %esi
- call mp_get_tpr_eax
- xchg %eax, %esi
- ret
-
-mp_get_tpr_edi:
- mov %eax, %edi
- call mp_get_tpr_edi
- xchg %eax, %edi
- ret
-
-mp_get_tpr_ebp:
- mov %eax, %ebp
- call mp_get_tpr_eax
- xchg %eax, %ebp
- ret
-
-mp_get_tpr_stack:
- call mp_get_tpr_eax
- xchg %eax, 4(%esp)
- ret
-
-mp_set_tpr_eax:
- push %eax
- call mp_set_tpr
- ret
-
-mp_set_tpr:
- pushf
- push %eax
- push %ecx
- push %edx
- push %ebx
- cli
- reenable_vtpr
-
-mp_set_tpr_failed:
- fs/movzbl pcr_cpu, %edx
-
- mov vcpu_shift, %ecx ; fixup
- shl %cl, %edx
-
- testb $1, vapic+4(%edx) ; fixup delta=-5
- jz mp_set_tpr_bad
-
- mov vapic(%edx), %eax ; fixup
-
- mov %eax, %ebx
- mov 24(%esp), %bl
-
- /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
-
- lock cmpxchg %ebx, vapic(%edx) ; fixup
- jnz mp_set_tpr_failed
-
- /* compute ppr */
- cmp %bh, %bl
- jae mp_tpr_is_bigger
-mp_isr_is_bigger:
- mov %bh, %bl
-mp_tpr_is_bigger:
- /* %bl = ppr */
- mov %bl, %ch /* ch = ppr */
- rol $8, %ebx
- /* now: %bl = irr, %bh = ppr */
- cmp %bh, %bl
- ja mp_set_tpr_poll_irq
-
-mp_set_tpr_out:
- pop %ebx
- pop %edx
- pop %ecx
- pop %eax
- popf
- ret $4
-
-mp_set_tpr_poll_irq:
- mov $kvm_hypercall_vapic_poll_irq, %eax
- kvm_hypercall
- jmp mp_set_tpr_out
-
-mp_set_tpr_bad:
- mov 24(%esp), %ecx
- mov real_tpr, %eax ; fixup
- mov %ecx, (%eax)
- jmp mp_set_tpr_out
-
-up_get_tpr_eax:
- reenable_vtpr
- movzbl vapic, %eax ; fixup
- ret
-
-up_get_tpr_ebx:
- reenable_vtpr
- movzbl vapic, %ebx ; fixup
- ret
-
-up_get_tpr_ecx:
- reenable_vtpr
- movzbl vapic, %ecx ; fixup
- ret
-
-up_get_tpr_edx:
- reenable_vtpr
- movzbl vapic, %edx ; fixup
- ret
-
-up_get_tpr_esi:
- reenable_vtpr
- movzbl vapic, %esi ; fixup
- ret
-
-up_get_tpr_edi:
- reenable_vtpr
- movzbl vapic, %edi ; fixup
- ret
-
-up_get_tpr_ebp:
- reenable_vtpr
- movzbl vapic, %ebp ; fixup
- ret
-
-up_get_tpr_stack:
- reenable_vtpr
- movzbl vapic, %eax ; fixup
- xchg %eax, 4(%esp)
- ret
-
-up_set_tpr_eax:
- push %eax
- call up_set_tpr
- ret
-
-up_set_tpr:
- pushf
- push %eax
- push %ecx
- push %ebx
- reenable_vtpr
-
-up_set_tpr_failed:
- mov vapic, %eax ; fixup
-
- mov %eax, %ebx
- mov 20(%esp), %bl
-
- /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
-
- lock cmpxchg %ebx, vapic ; fixup
- jnz up_set_tpr_failed
-
- /* compute ppr */
- cmp %bh, %bl
- jae up_tpr_is_bigger
-up_isr_is_bigger:
- mov %bh, %bl
-up_tpr_is_bigger:
- /* %bl = ppr */
- mov %bl, %ch /* ch = ppr */
- rol $8, %ebx
- /* now: %bl = irr, %bh = ppr */
- cmp %bh, %bl
- ja up_set_tpr_poll_irq
-
-up_set_tpr_out:
- pop %ebx
- pop %ecx
- pop %eax
- popf
- ret $4
-
-up_set_tpr_poll_irq:
- mov $kvm_hypercall_vapic_poll_irq, %eax
- kvm_hypercall
- jmp up_set_tpr_out
-
-.align 4096
-/*
- * vapic format:
- * per-vcpu records of size 2^vcpu shift.
- * byte 0: tpr (r/w)
- * byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
- * byte 2: zero (r/o)
- * byte 3: highest pending interrupt (irr) (r/o)
- */
-vapic:
-. = . + vapic_size