summaryrefslogtreecommitdiff
path: root/util/ADLO/bochs/bios
diff options
context:
space:
mode:
Diffstat (limited to 'util/ADLO/bochs/bios')
-rw-r--r--util/ADLO/bochs/bios/Makefile50
-rw-r--r--util/ADLO/bochs/bios/README1
-rw-r--r--util/ADLO/bochs/bios/rombios.c10551
3 files changed, 0 insertions, 10602 deletions
diff --git a/util/ADLO/bochs/bios/Makefile b/util/ADLO/bochs/bios/Makefile
deleted file mode 100644
index 49b702b3f3..0000000000
--- a/util/ADLO/bochs/bios/Makefile
+++ /dev/null
@@ -1,50 +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
-
-.SUFFIXES: .cc
-
-# -------- end configurable options --------------------------
-
-.cc.o:
- $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(BX_INCDIRS) $< -o $@
-
-bios: rombios.bin
-
-rombios.bin: rombios.c
- gcc -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 rombios.bin -u- -w- -g -0 -j -O -l rombios.txt
- ls -l rombios.bin
-
-# -----------------------------------------------------------------
-
-clean:
- rm -f *.s
- rm -f _rombios_.c
- rm -f rombios.txt
- rm -f rombios.bin
-
-
-# -----------------------------------------------------------------
diff --git a/util/ADLO/bochs/bios/README b/util/ADLO/bochs/bios/README
deleted file mode 100644
index b6b9549823..0000000000
--- a/util/ADLO/bochs/bios/README
+++ /dev/null
@@ -1 +0,0 @@
-The bochs bios.
diff --git a/util/ADLO/bochs/bios/rombios.c b/util/ADLO/bochs/bios/rombios.c
deleted file mode 100644
index 204300e3ea..0000000000
--- a/util/ADLO/bochs/bios/rombios.c
+++ /dev/null
@@ -1,10551 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id: rombios.c,v 1.163 2006/07/07 16:10:37 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/Plex x86 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)
-
-#define DEBUG_ROMBIOS 1
-
-#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 0
-
-#define COREBOOT 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 1 /* 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)
-
- // Define the application NAME
-#ifdef PLEX86
-# define BX_APPNAME "Plex86"
-#else
-# define BX_APPNAME "Bochs"
-#endif
-
- // 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 PANIC_PORT 0x400
-#define PANIC_PORT2 0x401
-#define INFO_PORT 0x402
-#define DEBUG_PORT 0x403
-
-// 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;
-
-#if BX_USE_ATADRV
-
- 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
- cmp cx, #0x00
- 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
- }
-
-#if 0
- // 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
- cmp cx, #0x0000
- 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
- cmp cx, #0x0000
- 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
- }
-#endif
-#endif //BX_USE_ATADRV
-
- // 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]
- inc bx
- inc bx
- 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
- inc bx
- inc bx
- 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
- add 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
- add 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
- add eax, ebx
- shr ebx, #16
- test eax, eax
- ret
-
- ;; sr function
- lsrul:
- mov cx,di
- jcxz lsr_exit
- and eax, #0x0000FFFF
- shl ebx, #16
- add 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
- add 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
- add 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 lba_capable; // LBA capable flag - always yes for bochs devices
- Bit8u mode; // transfert 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; // Total sectors count
- } 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
- 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_segment;
- Bit16u dpte_offset;
- 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;
-
-
-
-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 Bit32u 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 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.163 $ $Date: 2006/07/07 16:10:37 $";
-
-#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
-
-#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)
-
-#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 },
- { none, none, none, none, none },
- { 0x5700, 0x5700, none, none, none }, /* F11 */
- { 0x5800, 0x5800, none, none, 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');
-}
-
-//--------------------------------------------------------------------------
-// bios_printf()
-// A compact variable argument printf function which prints its output via
-// an I/O port so that it can be logged by Bochs/Plex.
-// Currently, only %x is supported (or %02x, %04x, etc).
-//
-// Supports %[format_width][format]
-// where format can be d,x,c,s
-//--------------------------------------------------------------------------
- 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;
-
- 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') {
- if (format_width == 0)
- format_width = 4;
- for (i=format_width-1; i>=0; i--) {
- nibble = (arg >> (4 * i)) & 0x000f;
- send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A'));
- }
- }
- else if (c == 'u') {
- put_uint(action, arg, format_width, 0);
- }
- else if (c == 'l') {
- s++;
- arg_ptr++; /* increment to next arg */
- hibyte = read_word(arg_seg, arg_ptr);
- put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
- }
- 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') {
- bios_printf(action & (~BIOS_PRINTF_HALT), 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 coreboot implementation of keyboard.c
-// could convert to #asm to gain space
- void
-keyboard_init()
-{
-#ifndef COREBOOT
- 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);
-#endif
-}
-
-//--------------------------------------------------------------------------
-// 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);
-}
-
-//--------------------------------------------------------------------------
-// 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(
-#ifdef BX_PCIBIOS
- "pcibios "
-#endif
-#ifdef BX_ELTORITO_BOOT
- "eltorito "
-#endif
- "\n\n");
-}
-
-//--------------------------------------------------------------------------
-// print_boot_device
-// displays the boot device
-//--------------------------------------------------------------------------
-
-static char drivetypes[][10]={"Floppy","Hard Disk","CD-Rom"};
-
-void
-print_boot_device(cdboot, drive)
- Bit8u cdboot; Bit16u drive;
-{
- Bit8u i;
-
- // cdboot contains 0 if floppy/harddisk, 1 otherwise
- // drive contains real/emulated boot drive
-
- if(cdboot)i=2; // CD-Rom
- else if((drive&0x0080)==0x00)i=0; // Floppy
- else if((drive&0x0080)==0x80)i=1; // Hard drive
- else return;
-
- printf("Booting from %s...\n",drivetypes[i]);
-}
-
-//--------------------------------------------------------------------------
-// print_boot_failure
-// displays the reason why boot failed
-//--------------------------------------------------------------------------
- void
-print_boot_failure(cdboot, drive, reason, lastdrive)
- Bit8u cdboot; Bit8u drive; Bit8u lastdrive;
-{
- Bit16u drivenum = drive&0x7f;
-
- // cdboot: 1 if boot from cd, 0 otherwise
- // drive : drive number
- // reason: 0 signature check failed, 1 read error
- // lastdrive: 1 boot drive is the last one in boot sequence
-
- if (cdboot)
- bios_printf(BIOS_PRINTF_INFO | BIOS_PRINTF_SCREEN, "Boot from %s failed\n",drivetypes[2]);
- else if (drive & 0x80)
- bios_printf(BIOS_PRINTF_INFO | BIOS_PRINTF_SCREEN, "Boot from %s %d failed\n", drivetypes[1],drivenum);
- else
- bios_printf(BIOS_PRINTF_INFO | BIOS_PRINTF_SCREEN, "Boot from %s %d failed\n", drivetypes[0],drivenum);
-
- if (lastdrive==1) {
- if (reason==0)
- BX_PANIC("Not a bootable disk\n");
- else
- BX_PANIC("Could not read the boot disk\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);
-}
-
-#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
-
-// 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_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,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);
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : device detection
-// ---------------------------------------------------------------------------
-
-void ata_detect( )
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u hdcount, cdcount, device, type;
- Bit8u buffer[0x0200];
- Bit16u i;
-
-#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;
- 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, 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
-
- sectors = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
-
- 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, sectors);
- 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 /= 63;
- heads = sectors / 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 / 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, 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);
- sizeinmb >>= 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;
- }
- 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);
- printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
- 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;
- 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
- max=0xff;
- while(--max>0) {
- Bit8u status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_BSY) != 0) break;
- }
-
-// 8.2.1 (f) -- clear SRST
- outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-
- if (read_byte(ebda_seg,&EbdaData->ata.devices[device].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) ) {
-
-// 8.2.1 (h) -- wait for not BSY
- max=0xff;
- while(--max>0) {
- Bit8u status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_BSY) == 0) break;
- }
- }
- }
-
-// 8.2.1 (i) -- wait for DRDY
- max=0xfff;
- while(--max>0) {
- Bit8u status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_RDY) != 0) break;
- }
-
- // 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, segment, offset)
-Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
-{
- 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;
-
- // sector will be 0 only on lba access. Convert to lba-chs
- if (sector == 0) {
- sector = (Bit16u) (lba & 0x000000ffL);
- lba >>= 8;
- cylinder = (Bit16u) (lba & 0x0000ffffL);
- lba >>= 16;
- head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
- }
-
- // 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);
- 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);
-
- while (1) {
- status = inb(iobase1 + ATA_CB_STAT);
- if ( !(status & ATA_CB_STAT_BSY) ) break;
- }
-
- 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--;
- 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, segment, offset)
-Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
-{
- 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;
-
- // sector will be 0 only on lba access. Convert to lba-chs
- if (sector == 0) {
- sector = (Bit16u) (lba & 0x000000ffL);
- lba >>= 8;
- cylinder = (Bit16u) (lba & 0x0000ffffL);
- lba >>= 16;
- head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
- }
-
- // 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);
- 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);
-
- while (1) {
- status = inb(iobase1 + ATA_CB_STAT);
- if ( !(status & ATA_CB_STAT_BSY) ) break;
- }
-
- 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
- while (1) {
- status = inb(iobase1 + ATA_CB_STAT);
- if ( !(status & ATA_CB_STAT_BSY) ) break;
- }
-
- 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) {
- status = inb(iobase1 + ATA_CB_STAT);
- }
- else {
- while (1) {
-
- status = inb(iobase1 + ATA_CB_STAT);
-
- // Check if command completed
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break;
-
- if (status & ATA_CB_STAT_ERR) {
- BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
- return 3;
- }
-
- // Device must be ready to send data
- 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_packet : not ready (status %02x)\n", status);
- return 4;
- }
-
- // 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)
- Bit16u device;
-{
- Bit8u atacmd[12];
- Bit8u buffer[16];
- Bit8u i;
-
- memsetb(get_SS(),atacmd,0,12);
-
- // Request SENSE
- atacmd[0]=0x03;
- atacmd[4]=0x20;
- if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, get_SS(), buffer) != 0)
- return 0x0002;
-
- if ((buffer[0] & 0x7e) == 0x70) {
- return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12];
- }
-
- return 0;
-}
-
- Bit16u
-atapi_is_ready(device)
- Bit16u device;
-{
- Bit8u atacmd[12];
- Bit8u buffer[];
-
- memsetb(get_SS(),atacmd,0,12);
-
- // Test Unit Ready
- if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
- return 0x000f;
-
- if (atapi_get_sense(device) !=0 ) {
- memsetb(get_SS(),atacmd,0,12);
-
- // try to send Test Unit Ready again
- if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
- return 0x000f;
-
- return atapi_get_sense(device);
- }
- 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;
-
- // 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);
-
- // limit to 15M
- if(regs.u.r16.ax > 0x3c00)
- regs.u.r16.ax = 0x3c00;
-
- 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");
- // BX:
- // 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
- CLEAR_CF();
- regs.u.r8.ah = 0;
- 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
-
-
-void set_e820_range(ES, DI, start, end, type)
- Bit16u ES;
- Bit16u DI;
- Bit32u start;
- Bit32u end;
- Bit16u type;
-{
- write_word(ES, DI, start);
- write_word(ES, DI+2, start >> 16);
- write_word(ES, DI+4, 0x00);
- write_word(ES, DI+6, 0x00);
-
- end -= start;
- write_word(ES, DI+8, end);
- write_word(ES, DI+10, end >> 16);
- write_word(ES, DI+12, 0x0000);
- 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
- Bit16u CX,DX;
-
-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_function.CX [bx]
- shl eax, #16
- SEG SS
- mov ax, _int15_function.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)
- {
- switch(regs.u.r16.bx)
- {
- case 0:
- set_e820_range(ES, regs.u.r16.di,
- 0x0000000L, 0x0009fc00L, 1);
- regs.u.r32.ebx = 1;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- case 1:
- set_e820_range(ES, regs.u.r16.di,
- 0x0009fc00L, 0x000a0000L, 2);
- regs.u.r32.ebx = 2;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- case 2:
- set_e820_range(ES, regs.u.r16.di,
- 0x000e8000L, 0x00100000L, 2);
- regs.u.r32.ebx = 3;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- case 3:
- extended_memory_size = inb_cmos(0x35);
- extended_memory_size <<= 8;
- extended_memory_size |= inb_cmos(0x34);
- extended_memory_size *= 64;
- if(extended_memory_size > 0x3bc000) // greater than EFF00000???
- {
- 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;
- }
-
- set_e820_range(ES, regs.u.r16.di,
- 0x00100000L, extended_memory_size, 1);
- regs.u.r32.ebx = 4;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- break;
- case 4:
- /* 256KB BIOS area at the end of 4 GB */
- set_e820_range(ES, regs.u.r16.di,
- 0xfffc0000L, 0x00000000L, 2);
- regs.u.r32.ebx = 0;
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
- return;
- default: /* AX=E820, DX=534D4150, BX unrecognized */
- goto int15_unimplemented;
- break;
- }
- } 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, count;
- Bit16u kbd_code, max;
-
- BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
-
- 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, led_flags;
-
- //
- // 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);
- led_flags = read_byte(0x0040, 0x97);
- asciicode = 0;
-
- switch (scancode) {
- case 0x3a: /* Caps Lock press */
- shift_flags ^= 0x40;
- write_byte(0x0040, 0x17, shift_flags);
- mf2_flags |= 0x40;
- led_flags ^= 0x04;
- write_byte(0x0040, 0x18, mf2_flags);
- write_byte(0x0040, 0x97, led_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;
- led_flags ^= 0x02;
- write_byte(0x0040, 0x17, shift_flags);
- write_byte(0x0040, 0x97, led_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;
- led_flags ^= 0x01;
- write_byte(0x0040, 0x17, shift_flags);
- write_byte(0x0040, 0x97, led_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 (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(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;
-{
- Bit32u lba;
- 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) ) {
- BX_INFO("int13_harddisk: function %02x, count 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 = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
- 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, segment, offset);
- else
- status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, 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 physical geometry from table
- 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);
-
- // Compute sector count seen by int13
- lba = (Bit32u)(npc - 1) * (Bit32u)nph * (Bit32u)npspt;
- CX = lba >> 16;
- DX = lba & 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);
-
- // Can't use 64 bits lba
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
- if (lba != 0L) {
- BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH());
- goto int13_fail;
- }
-
- // Get 32 bits lba and check
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
- if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) {
- 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, segment, offset);
- else
- status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, 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 = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors);
- 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, 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); // FIXME should be Bit64
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);
- 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);
- 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, (&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("int13h_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 15
- 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);
- 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, (&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(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, 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); // HD0: 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
-
-
-//////////////////////
-// 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);
-}
-
-#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 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) ||
- (num_sectors == 0) || (num_sectors > 72) ) {
-BX_INFO("floppy: drive>1 || head>1 ...\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
- }
-}
-
-// returns bootsegment in ax, drive in bl
- Bit32u
-int19_function(bseqnr)
-Bit8u bseqnr;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit16u bootseq;
- Bit8u bootdrv;
- Bit8u bootcd;
- Bit8u bootchk;
- Bit16u bootseg;
- Bit16u status;
- Bit8u lastdrive=0;
-
- // 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
- // else : boot failure
-
- // Get the boot sequence
-#if BX_ELTORITO_BOOT
- bootseq=inb_cmos(0x3d);
- bootseq|=((inb_cmos(0x38) & 0xf0) << 4);
-
- if (bseqnr==2) bootseq >>= 4;
- if (bseqnr==3) bootseq >>= 8;
- if (bootseq<0x10) lastdrive = 1;
- bootdrv=0x00; bootcd=0;
- switch(bootseq & 0x0f) {
- case 0x01: bootdrv=0x00; bootcd=0; break;
- case 0x02: bootdrv=0x80; bootcd=0; break;
- case 0x03: bootdrv=0x00; bootcd=1; break;
- default: return 0x00000000;
- }
-#else
- bootseq=inb_cmos(0x2d);
-
- if (bseqnr==2) {
- bootseq ^= 0x20;
- lastdrive = 1;
- }
- bootdrv=0x00; bootcd=0;
- if((bootseq&0x20)==0) bootdrv=0x80;
-#endif // BX_ELTORITO_BOOT
-
-#if BX_ELTORITO_BOOT
- // We have to boot from cd
- if (bootcd != 0) {
- status = cdrom_boot();
-
- // If failure
- if ( (status & 0x00ff) !=0 ) {
- print_cdromboot_failure(status);
- print_boot_failure(bootcd, bootdrv, 1, lastdrive);
- return 0x00000000;
- }
-
- bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment);
- bootdrv = (Bit8u)(status>>8);
- }
-
-#endif // BX_ELTORITO_BOOT
-
- // We have to boot from harddisk or floppy
- if (bootcd == 0) {
- bootseg=0x07c0;
-
-ASM_START
- push bp
- mov bp, sp
-
- mov ax, #0x0000
- mov _int19_function.status + 2[bp], ax
- mov dl, _int19_function.bootdrv + 2[bp]
- mov ax, _int19_function.bootseg + 2[bp]
- mov es, ax ;; segment
- mov bx, #0x0000 ;; 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 bp
-ASM_END
-
- if (status != 0) {
- print_boot_failure(bootcd, bootdrv, 1, lastdrive);
- return 0x00000000;
- }
- }
-
- // check signature if instructed by cmos reg 0x38, only for floppy
- // bootchk = 1 : signature check disabled
- // bootchk = 0 : signature check enabled
- if (bootdrv != 0) bootchk = 0;
- else bootchk = inb_cmos(0x38) & 0x01;
-
-#if BX_ELTORITO_BOOT
- // if boot from cd, no signature check
- if (bootcd != 0)
- bootchk = 1;
-#endif // BX_ELTORITO_BOOT
-
- if (bootchk == 0) {
- if (read_word(bootseg,0x1fe) != 0xaa55) {
- print_boot_failure(bootcd, bootdrv, 0, lastdrive);
- return 0x00000000;
- }
- }
-
-#if BX_ELTORITO_BOOT
- // Print out the boot string
- print_boot_device(bootcd, bootdrv);
-#else // BX_ELTORITO_BOOT
- print_boot_device(0, bootdrv);
-#endif // BX_ELTORITO_BOOT
-
- // return the boot segment
- return (((Bit32u)bootdrv) << 16) + bootseg;
-}
-
- 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) {
- BX_INFO("PCI device %04x:%04x not found at index %d\n", regs.u.r16.dx, regs.u.r16.cx, 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:
- call _int13_harddisk
-
-int13_out:
- pop ds
- pop es
- popa
- iret
-
-
-;----------
-;- INT18h -
-;----------
-int18_handler: ;; Boot Failure routing
- call _int18_panic_msg
- hlt
- iret
-
-;----------
-;- INT19h -
-;----------
-int19_relocated: ;; Boot function, relocated
-
- ;; int19 was beginning to be really complex, so now it
- ;; just calls an C function, that does the work
- ;; it returns in BL the boot drive, and in AX the boot segment
- ;; the boot segment will be 0x0000 if something has failed
-
- push bp
- mov bp, sp
-
- ;; drop ds
- xor ax, ax
- mov ds, ax
-
- ;; 1st boot device
- mov ax, #0x0001
- push ax
- call _int19_function
- inc sp
- inc sp
- ;; bl contains the boot drive
- ;; ax contains the boot segment or 0 if failure
-
- test ax, ax ;; if ax is 0 try next boot device
- jnz boot_setup
-
- ;; 2nd boot device
- mov ax, #0x0002
- push ax
- call _int19_function
- inc sp
- inc sp
- test ax, ax ;; if ax is 0 try next boot device
- jnz boot_setup
-
- ;; 3rd boot device
- mov ax, #0x0003
- push ax
- call _int19_function
- inc sp
- inc sp
- test ax, ax ;; if ax is 0 call int18
- jz int18_handler
-
-boot_setup:
- mov dl, bl ;; set drive so guest os find it
- shl eax, #0x04 ;; convert seg to ip
- mov 2[bp], ax ;; set ip
-
- shr eax, #0x04 ;; get cs back
- and ax, #0xF000 ;; remove what went in ip
- mov 4[bp], ax ;; set cs
- xor ax, ax
- mov es, ax ;; set es to zero fixes [ 549815 ]
- mov [bp], ax ;; set bp to zero
- mov ax, #0xaa55 ;; set ok flag
-
- pop bp
- iret ;; Beam me up Scotty
-
-;----------
-;- INT1Ch -
-;----------
-int1c_handler: ;; User Timer Tick
- iret
-
-
-;----------------------
-;- POST: Floppy Drive -
-;----------------------
-floppy_drive_post:
- mov ax, #0x0000
- 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
-
- mov ax, #0x0000
- 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:
- call eoi_both_pics
-
- xor ax, ax
- mov ds, ax
-
- jmp far ptr [0x467]
-
-
-;--------------------
-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_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:
- pushf
- 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:
- popf
- retf
-
-.align 16
-pcibios_protected:
- pushf
- 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_f08
- shl ecx, #16
- mov cx, dx
- mov bx, #0x0000
- 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_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
- popf
- stc
- retf
-pci_pro_ok:
- xor ah, ah
- pop edi
- pop esi
- popf
- 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_f08
- shl ecx, #16
- mov cx, dx
- mov bx, #0x0000
- 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 ah, #0x86
- 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 0x7000 ;; 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 0x07 ;; 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:
-
-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 eax, dx
- cmp eax, [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
- inc dx
- inc dx
- 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_PCIBIOS
-
-; 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
-
-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)
-
- mov cx, #0xc000
-rom_scan_loop:
- 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:
-
- xor bx, bx ;; Restore DS back to 0000:
- mov ds, bx
- push ax ;; Save AX
- ;; Push addr of ROM entry point
- push cx ;; Push seg
- push #0x0003 ;; Push offset
- 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)
- 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
- cmp cx, #0xe000
- jbe rom_scan_loop
-
- xor ax, ax ;; Restore DS back to 0000:
- mov ds, ax
- ret
-
-;; for 'C' strings and other data, insert them here with
-;; a the following hack:
-;; DATA_SEG_DEFS_HERE
-
-
-;--------
-;- POST -
-;--------
-.org 0xe05b ; POST Entry Point
-post:
-
- 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
-
- ;; Examine CMOS shutdown status.
- ;; 0x01,0x02,0x03,0x04,0x06,0x07,0x08, 0x0a, 0x0b, 0x0c = 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
- mov ax, #0x0000
- mov ds, ax
- mov ss, ax
-
- ;; 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
- mov bx, #0x0000 ;; offset index
- mov cx, #0x0100 ;; counter (256 interrupts)
- mov ax, #dummy_iret_handler
- mov dx, #0xF000
-
-post_default_ints:
- mov [bx], ax
- inc bx
- inc bx
- mov [bx], dx
- inc bx
- inc bx
- 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
- 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
-
-#if BX_PCIBIOS
- call pcibios_init_iomem_bases
- call pcibios_init_irqs
-#endif
-
- call rom_scan
-
- call _print_bios_banner
-
- ;;
- ;; Floppy setup
- ;;
- call floppy_drive_post
-
-#if BX_USE_ATADRV
-
- ;;
- ;; Hard Drive setup
- ;;
- call hard_drive_post
-
- ;;
- ;; ATA/ATAPI driver setup
- ;;
- call _ata_init
- call _ata_detect
- ;;
-#else // BX_USE_ATADRV
-
- ;;
- ;; Hard Drive setup
- ;;
- call hard_drive_post
-
-#endif // BX_USE_ATADRV
-
-#if BX_ELTORITO_BOOT
- ;;
- ;; eltorito floppy/harddisk emulation from cd
- ;;
- call _cdemu_init
- ;;
-#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
- mov ax, #0x0000
- 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
- mov ax, #0x0000 ;; 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
- mov ax, #0x0000
- 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
- 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_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
-// bcc-generated data will be placed here
-ASM_END