aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware/rombios
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-12-18 14:52:53 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-12-18 14:52:53 +0000
commite8a33bc38fc7d70fcf3a00d41305c997e46ddf2d (patch)
tree2e857b6084feb9e7b4039550b1d41a29d612807a /tools/firmware/rombios
parentdce021d06abfae3cb5613c1a7856cff56f79c5ad (diff)
downloadxen-e8a33bc38fc7d70fcf3a00d41305c997e46ddf2d.tar.gz
xen-e8a33bc38fc7d70fcf3a00d41305c997e46ddf2d.tar.bz2
xen-e8a33bc38fc7d70fcf3a00d41305c997e46ddf2d.zip
rombios: Update to Bochs latest
Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
Diffstat (limited to 'tools/firmware/rombios')
-rw-r--r--tools/firmware/rombios/rombios.c3523
-rw-r--r--tools/firmware/rombios/rombios.h70
2 files changed, 2109 insertions, 1484 deletions
diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c
index 51370a9c54..1f65202074 100644
--- a/tools/firmware/rombios/rombios.c
+++ b/tools/firmware/rombios/rombios.c
@@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
-// $Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $
+// $Id: rombios.c,v 1.221 2008/12/07 17:32:29 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@@ -22,9 +22,9 @@
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-// ROM BIOS for use with Bochs/Plex x86 emulation environment
+// ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
#define uint8_t unsigned char
#define uint16_t unsigned short
@@ -81,10 +81,10 @@
//
// 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 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.
+// - 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:
@@ -102,13 +102,13 @@
// 12 : can not read cd - boot image
//
// ATA driver
-// - EBDA segment.
+// - EBDA segment.
// I used memory starting at 0x121 in the segment
// - the translation policy is defined in cmos regs 0x39 & 0x3a
//
// TODO :
//
-// int74
+// int74
// - needs to be reworked. Uses direct [bp] offsets. (?)
//
// int13:
@@ -128,13 +128,13 @@
// - 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.
+// 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 0
+#include "rombios.h"
#define DEBUG_ATA 0
#define DEBUG_INT13_HD 0
@@ -159,7 +159,7 @@
#define BX_USE_ATADRV 1
#define BX_ELTORITO_BOOT 1
-#define BX_TCGBIOS 0 /* main switch for TCG BIOS ext. */
+#define BX_TCGBIOS 0 /* main switch for TCG BIOS ext. */
#define BX_MAX_ATA_INTERFACES 4
#define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2)
@@ -181,7 +181,6 @@
// EBDA is used for PS/2 mouse support, and IDE BIOS, etc.
#define EBDA_SEG 0x9FC0
#define EBDA_SIZE 1 // In KiB
-#define EBDA_SEG_PTR 0x40E /* Find true EBDA segment at 0:40E */
#define BASE_MEM_IN_K (640 - EBDA_SIZE)
/* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
@@ -189,15 +188,13 @@
#define IPL_TABLE_ENTRIES 8
#define IPL_COUNT_OFFSET 0x0380 /* u16: number of valid table entries */
#define IPL_SEQUENCE_OFFSET 0x0382 /* u16: next boot device */
+#define IPL_BOOTFIRST_OFFSET 0x0384 /* u16: user selected device */
+#define IPL_SIZE 0xff
+#define IPL_TYPE_FLOPPY 0x01
+#define IPL_TYPE_HARDDISK 0x02
+#define IPL_TYPE_CDROM 0x03
+#define IPL_TYPE_BEV 0x80
- // Define the application NAME
-#ifdef HVMASSIST
-# define BX_APPNAME "HVMAssist"
-#elif PLEX86
-# define BX_APPNAME "Plex86"
-#else
-# define BX_APPNAME "Bochs"
-#endif
// Sanity Checks
#if BX_USE_ATADRV && BX_CPU<3
@@ -216,15 +213,10 @@
# error APM BIOS can only be used with 386+ cpu
#endif
-#ifndef BX_SMP_PROCESSORS
-#define BX_SMP_PROCESSORS 1
-# warning BX_SMP_PROCESSORS not defined, defaulting to 1
-#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
@@ -257,7 +249,7 @@ use16 286
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
+ ;; 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.
@@ -296,9 +288,9 @@ typedef unsigned long Bit32u;
void memsetb(seg,offset,value,count);
void memcpyb(dseg,doffset,sseg,soffset,count);
void memcpyd(dseg,doffset,sseg,soffset,count);
-
+
// memset of count bytes
- void
+ void
memsetb(seg,offset,value,count)
Bit16u seg;
Bit16u offset;
@@ -308,14 +300,14 @@ typedef unsigned long Bit32u;
ASM_START
push bp
mov bp, sp
-
+
push ax
push cx
push es
push di
-
+
mov cx, 10[bp] ; count
- cmp cx, #0x00
+ test cx, cx
je memsetb_end
mov ax, 4[bp] ; segment
mov es, ax
@@ -325,19 +317,19 @@ typedef unsigned long Bit32u;
cld
rep
stosb
-
+
memsetb_end:
pop di
pop es
pop cx
pop ax
-
+
pop bp
ASM_END
}
-
+
// memcpy of count bytes
- void
+ void
memcpyb(dseg,doffset,sseg,soffset,count)
Bit16u dseg;
Bit16u doffset;
@@ -348,16 +340,16 @@ typedef unsigned long Bit32u;
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
+ test cx, cx
je memcpyb_end
mov ax, 4[bp] ; dsegment
mov es, ax
@@ -370,7 +362,7 @@ typedef unsigned long Bit32u;
cld
rep
movsb
-
+
memcpyb_end:
pop si
pop ds
@@ -378,14 +370,13 @@ typedef unsigned long Bit32u;
pop es
pop cx
pop ax
-
+
pop bp
ASM_END
}
-#if 0
// memcpy of count dword
- void
+ void
memcpyd(dseg,doffset,sseg,soffset,count)
Bit16u dseg;
Bit16u doffset;
@@ -396,16 +387,16 @@ typedef unsigned long Bit32u;
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
+ test cx, cx
je memcpyd_end
mov ax, 4[bp] ; dsegment
mov es, ax
@@ -418,7 +409,7 @@ typedef unsigned long Bit32u;
cld
rep
movsd
-
+
memcpyd_end:
pop si
pop ds
@@ -426,16 +417,15 @@ typedef unsigned long Bit32u;
pop es
pop cx
pop ax
-
+
pop bp
ASM_END
}
-#endif
// read_dword and write_dword functions
static Bit32u read_dword();
static void write_dword();
-
+
Bit32u
read_dword(seg, offset)
Bit16u seg;
@@ -444,25 +434,24 @@ typedef unsigned long Bit32u;
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
+ add bx, #2
mov dx, [bx]
;; ax = return value (word)
;; dx = return value (word)
pop ds
pop bx
-
+
pop bp
ASM_END
}
-
+
void
write_dword(seg, offset, data)
Bit16u seg;
@@ -472,7 +461,7 @@ typedef unsigned long Bit32u;
ASM_START
push bp
mov bp, sp
-
+
push ax
push bx
push ds
@@ -481,50 +470,49 @@ typedef unsigned long Bit32u;
mov bx, 6[bp] ; offset
mov ax, 8[bp] ; data word
mov [bx], ax ; write data word
- inc bx
- inc bx
+ add bx, #2
mov ax, 10[bp] ; data word
mov [bx], ax ; write data word
pop ds
pop bx
pop ax
-
+
pop bp
ASM_END
}
-
+
// Bit32u (unsigned long) and long helper functions
ASM_START
-
+
;; and function
landl:
landul:
- SEG SS
+ SEG SS
and ax,[di]
- SEG SS
+ SEG SS
and bx,2[di]
ret
-
+
;; add function
laddl:
laddul:
- SEG SS
+ SEG SS
add ax,[di]
- SEG SS
+ SEG SS
adc bx,2[di]
ret
-
+
;; cmp function
lcmpl:
lcmpul:
and eax, #0x0000FFFF
shl ebx, #16
- add eax, ebx
+ or eax, ebx
shr ebx, #16
SEG SS
cmp eax, dword ptr [di]
ret
-
+
;; sub function
lsubl:
lsubul:
@@ -533,26 +521,26 @@ typedef unsigned long Bit32u;
SEG SS
sbb bx,2[di]
ret
-
+
;; mul function
lmull:
lmulul:
and eax, #0x0000FFFF
shl ebx, #16
- add eax, ebx
+ or eax, ebx
SEG SS
mul eax, dword ptr [di]
mov ebx, eax
shr ebx, #16
ret
-
+
;; dec function
ldecl:
ldecul:
SEG SS
dec dword ptr [bx]
ret
-
+
;; or function
lorl:
lorul:
@@ -561,31 +549,31 @@ typedef unsigned long Bit32u;
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
+ or eax, ebx
shr ebx, #16
test eax, eax
ret
-
+
;; sr function
lsrul:
mov cx,di
jcxz lsr_exit
and eax, #0x0000FFFF
shl ebx, #16
- add eax, ebx
+ or eax, ebx
lsr_loop:
shr eax, #1
loop lsr_loop
@@ -593,7 +581,7 @@ typedef unsigned long Bit32u;
shr ebx, #16
lsr_exit:
ret
-
+
;; sl function
lsll:
lslul:
@@ -601,15 +589,15 @@ typedef unsigned long Bit32u;
jcxz lsl_exit
and eax, #0x0000FFFF
shl ebx, #16
- add eax, ebx
- lsl_loop:
+ or eax, ebx
+ lsl_loop:
shl eax, #1
loop lsl_loop
mov ebx, eax
shr ebx, #16
lsl_exit:
ret
-
+
idiv_:
cwd
idiv bx
@@ -623,7 +611,7 @@ typedef unsigned long Bit32u;
ldivul:
and eax, #0x0000FFFF
shl ebx, #16
- add eax, ebx
+ or eax, ebx
xor edx, edx
SEG SS
mov bx, 2[di]
@@ -672,7 +660,7 @@ typedef struct {
Bit8u revision;
Bit8u checksum;
} dpte_t;
-
+
typedef struct {
Bit8u iface; // ISA or PCI
Bit16u iobase1; // IO Base 1
@@ -685,15 +673,15 @@ typedef struct {
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
+ Bit8u mode; // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA
Bit16u blksize; // block size
Bit8u translation; // type of translation
chs_t lchs; // Logical CHS
chs_t pchs; // Physical CHS
- Bit32u sectors; // Total sectors count
+ Bit32u sectors_low; // Total sectors count
+ Bit32u sectors_high;
} ata_device_t;
typedef struct {
@@ -704,10 +692,10 @@ typedef struct {
ata_device_t devices[BX_MAX_ATA_DEVICES];
//
// map between (bios hd id - 0x80) and ata channels
- Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES];
+ Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES];
// map between (bios cd id - 0xE0) and ata channels
- Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES];
+ Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES];
// Buffer for DPTE table
dpte_t dpte;
@@ -717,9 +705,9 @@ typedef struct {
Bit32u trsfbytes;
} ata_t;
-
+
#if BX_ELTORITO_BOOT
- // ElTorito Device Emulation data
+ // ElTorito Device Emulation data
typedef struct {
Bit8u active;
Bit8u media;
@@ -730,20 +718,20 @@ typedef struct {
Bit16u buffer_segment;
Bit16u load_segment;
Bit16u sector_count;
-
+
// Virtual device
chs_t vdevice;
} cdemu_t;
#endif // BX_ELTORITO_BOOT
-
+
#include "32bitgateway.h"
// for access to EBDA area
- // The EBDA structure should conform to
- // http://www.cybertrails.com/~fys/rombios.htm document
+ // The EBDA structure should conform to
+ // http://www.frontiernet.net/~fys/rombios.htm document
// I made the ata and cdemu structs begin at 0x121 in the EBDA seg
- // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot
- // device tables are at 0x9ff00 -- 0x9ffff
+ // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot
+ // device tables are at EBDA_SEG:IPL_TABLE_OFFSET
typedef struct {
unsigned char ebda_size;
unsigned char cmos_shutdown_status;
@@ -765,7 +753,7 @@ typedef struct {
upcall_t upcall;
} ebda_data_t;
-
+
#define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1
#define EbdaData ((ebda_data_t *) 0)
@@ -779,7 +767,7 @@ typedef struct {
Bit32u lba1;
Bit32u lba2;
} int13ext_t;
-
+
#define Int13Ext ((int13ext_t *) 0)
// Disk Physical Table definition
@@ -805,7 +793,7 @@ typedef struct {
Bit8u reserved3;
Bit8u checksum;
} dpt_t;
-
+
#define Int13DPT ((dpt_t *) 0)
#endif // BX_USE_ATADRV
@@ -835,9 +823,9 @@ typedef struct {
} r16;
struct {
Bit32u filler[4];
- Bit8u bl, bh;
+ Bit8u bl, bh;
Bit16u filler1;
- Bit8u dl, dh;
+ Bit8u dl, dh;
Bit16u filler2;
Bit8u cl, ch;
Bit16u filler3;
@@ -871,6 +859,14 @@ typedef struct {
flags_t flags;
} iret_addr_t;
+typedef struct {
+ Bit16u type;
+ Bit16u flags;
+ Bit32u vector;
+ Bit32u description;
+ Bit32u reserved;
+ } ipl_entry_t;
+
static Bit8u inb();
@@ -910,8 +906,6 @@ static void int1a_function();
static void int70_function();
static void int74_function();
static Bit16u get_CS();
-//static Bit16u get_DS();
-//static void set_DS();
static Bit16u get_SS();
static unsigned int enqueue_key();
static unsigned int dequeue_key();
@@ -930,7 +924,10 @@ static void keyboard_init();
static void keyboard_panic();
static void shutdown_status_panic();
static void nmi_handler_msg();
+static void delay_ticks();
+static void delay_ticks_and_check_for_keystroke();
+static void interactive_bootkey();
static void print_bios_banner();
static void print_boot_device();
static void print_boot_failure();
@@ -964,33 +961,9 @@ Bit16u cdrom_boot();
#endif // BX_ELTORITO_BOOT
-static char bios_cvs_version_string[] = "$Revision: 1.138 $";
-static char bios_date_string[] = "$Date: 2005/05/07 15:55:26 $";
-
-static char CVSID[] = "$Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $";
-
-/* Offset to skip the CVS $Id: prefix */
-#define bios_version_string (CVSID + 4)
-
-#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)
+static char bios_cvs_version_string[] = "$Revision: 1.221 $ $Date: 2008/12/07 17:32:29 $";
-#define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
-
-// Defines the output macros.
-// BX_DEBUG goes to INFO port until we can easily choose debug info on a
-// per-device basis. Debug info are sent only in debug mode
-#if DEBUG_ROMBIOS
-# define BX_DEBUG(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
-#else
-# define BX_DEBUG(format, p...)
-#endif
-#define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
-#define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
+#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
#if DEBUG_ATA
# define BX_DEBUG_ATA(a...) BX_DEBUG(a)
@@ -1163,9 +1136,9 @@ static struct {
{ 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 }, /* ??? */
+ { none, none, none, none, none },
+ { none, none, none, none, none },
+ { 0x565c, 0x567c, none, none, none }, /* \| */
{ 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
{ 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */
};
@@ -1422,31 +1395,6 @@ ASM_START
ASM_END
}
-// Bit16u
-//get_DS()
-//{
-//ASM_START
-// mov ax, ds
-//ASM_END
-//}
-//
-// void
-//set_DS(ds_selector)
-// Bit16u ds_selector;
-//{
-//ASM_START
-// push bp
-// mov bp, sp
-//
-// push ax
-// mov ax, 4[bp] ; ds_selector
-// mov ds, ax
-// pop ax
-//
-// pop bp
-//ASM_END
-//}
-
Bit16u
get_SS()
{
@@ -1462,7 +1410,7 @@ copy_e820_table()
Bit8u nr_entries = read_byte(0x9000, 0x1e8);
Bit32u base_mem;
if (nr_entries > 32)
- nr_entries = 32;
+ nr_entries = 32;
write_word(0xe000, 0x8, nr_entries);
memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
/* Report the proper base memory size at address 0x0413: otherwise
@@ -1570,7 +1518,7 @@ wrch(c)
pop bp
ASM_END
}
-
+
void
send(action, c)
Bit16u action;
@@ -1626,14 +1574,121 @@ put_uint(action, val, width, neg)
send(action, val - (nval * 10) + '0');
}
+ void
+put_luint(action, val, width, neg)
+ Bit16u action;
+ unsigned long val;
+ short width;
+ bx_bool neg;
+{
+ unsigned long nval = val / 10;
+ if (nval)
+ put_luint(action, nval, width - 1, neg);
+ else {
+ while (--width > 0) send(action, ' ');
+ if (neg) send(action, '-');
+ }
+ send(action, val - (nval * 10) + '0');
+}
+
+void put_str(action, segment, offset)
+ Bit16u action;
+ Bit16u segment;
+ Bit16u offset;
+{
+ Bit8u c;
+
+ while (c = read_byte(segment, offset)) {
+ send(action, c);
+ offset++;
+ }
+}
+
+ void
+delay_ticks(ticks)
+ Bit16u ticks;
+{
+ long ticks_to_wait, delta;
+ Bit32u prev_ticks, t;
+
+ /*
+ * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
+ * We also have to be careful about interrupt storms.
+ */
+ASM_START
+ pushf
+ sti
+ASM_END
+ ticks_to_wait = ticks;
+ prev_ticks = read_dword(0x0, 0x46c);
+ do
+ {
+ASM_START
+ hlt
+ASM_END
+ t = read_dword(0x0, 0x46c);
+ if (t > prev_ticks)
+ {
+ delta = t - prev_ticks; /* The temp var is required or bcc screws up. */
+ ticks_to_wait -= delta;
+ }
+ else if (t < prev_ticks)
+ {
+ ticks_to_wait -= t; /* wrapped */
+ }
+
+ prev_ticks = t;
+ } while (ticks_to_wait > 0);
+ASM_START
+ cli
+ popf
+ASM_END
+}
+
+ Bit8u
+check_for_keystroke()
+{
+ASM_START
+ mov ax, #0x100
+ int #0x16
+ jz no_key
+ mov al, #1
+ jmp done
+no_key:
+ xor al, al
+done:
+ASM_END
+}
+
+ Bit8u
+get_keystroke()
+{
+ASM_START
+ mov ax, #0x0
+ int #0x16
+ xchg ah, al
+ASM_END
+}
+
+ void
+delay_ticks_and_check_for_keystroke(ticks, count)
+ Bit16u ticks, count;
+{
+ Bit16u i;
+ for (i = 1; i <= count; i++) {
+ delay_ticks(ticks);
+ if (check_for_keystroke())
+ break;
+ }
+}
+
//--------------------------------------------------------------------------
// bios_printf()
-// A compact variable argument printf function 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).
+// A compact variable argument printf function.
//
-// Supports %[format_width][format]
-// where format can be d,x,c,s
+// Supports %[format_width][length]format
+// where format can be x,X,u,d,s,S,c
+// and the optional length modifier is l (ell)
//--------------------------------------------------------------------------
void
bios_printf(action, s)
@@ -1644,7 +1699,7 @@ bios_printf(action, s)
bx_bool in_format;
short i;
Bit16u *arg_ptr;
- Bit16u arg_seg, arg, nibble, shift_count, format_width;
+ Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd;
arg_ptr = &s;
arg_seg = get_SS();
@@ -1671,17 +1726,49 @@ bios_printf(action, s)
else {
arg_ptr++; // increment to next arg
arg = read_word(arg_seg, arg_ptr);
- if (c == 'x') {
+ if (c == 'x' || c == 'X') {
if (format_width == 0)
format_width = 4;
+ if (c == 'x')
+ hexadd = 'a';
+ else
+ hexadd = 'A';
for (i=format_width-1; i>=0; i--) {
nibble = (arg >> (4 * i)) & 0x000f;
- send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A'));
+ send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
}
}
else if (c == 'u') {
put_uint(action, arg, format_width, 0);
}
+ else if (c == 'l') {
+ s++;
+ c = read_byte(get_CS(), s); /* is it ld,lx,lu? */
+ arg_ptr++; /* increment to next arg */
+ hibyte = read_word(arg_seg, arg_ptr);
+ if (c == 'd') {
+ if (hibyte & 0x8000)
+ put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1);
+ else
+ put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
+ }
+ else if (c == 'u') {
+ put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
+ }
+ else if (c == 'x' || c == 'X')
+ {
+ if (format_width == 0)
+ format_width = 8;
+ if (c == 'x')
+ hexadd = 'a';
+ else
+ hexadd = 'A';
+ for (i=format_width-1; i>=0; i--) {
+ nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f;
+ send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
+ }
+ }
+ }
else if (c == 'd') {
if (arg & 0x8000)
put_int(action, -arg, format_width - 1, 1);
@@ -1689,7 +1776,13 @@ bios_printf(action, s)
put_int(action, arg, format_width, 0);
}
else if (c == 's') {
- bios_printf(action & (~BIOS_PRINTF_HALT), arg);
+ put_str(action, get_CS(), arg);
+ }
+ else if (c == 'S') {
+ hibyte = arg;
+ arg_ptr++;
+ arg = read_word(arg_seg, arg_ptr);
+ put_str(action, hibyte, arg);
}
else if (c == 'c') {
send(action, arg);
@@ -1706,7 +1799,7 @@ bios_printf(action, s)
}
if (action & BIOS_PRINTF_HALT) {
- // freeze in a busy loop.
+ // freeze in a busy loop.
ASM_START
cli
halt2_loop:
@@ -1740,8 +1833,8 @@ keyboard_init()
max = 0x2000;
}
}
-
- // Due to timer issues, and if the IPS setting is > 15000000,
+
+ // 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
@@ -1878,13 +1971,12 @@ keyboard_init()
keyboard_panic(status)
Bit16u status;
{
- // If you're getting a 993 keyboard panic here,
+ // If you're getting a 993 keyboard panic here,
// please see the comment in keyboard_init
-
+
BX_PANIC("Keyboard error:%u\n",status);
}
-
#define CMOS_SHUTDOWN_S3 0xFE
//--------------------------------------------------------------------------
// machine_reset
@@ -1939,6 +2031,11 @@ shutdown_status_panic(status)
BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
}
+void s3_resume_panic()
+{
+ BX_PANIC("Returned from s3_resume.\n");
+}
+
//--------------------------------------------------------------------------
// print_bios_banner
// displays a the bios version
@@ -1946,74 +2043,84 @@ shutdown_status_panic(status)
void
print_bios_banner()
{
- printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":"");
- printf("%s %s\n", bios_cvs_version_string, bios_date_string);
+ printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
+ BIOS_BUILD_DATE, bios_cvs_version_string);
+ printf(
+#if BX_APM
+ "apmbios "
+#endif
+#if BX_PCIBIOS
+ "pcibios "
+#endif
+#if BX_ELTORITO_BOOT
+ "eltorito "
+#endif
+#if BX_ROMBIOS32
+ "rombios32 "
+#endif
#if BX_TCGBIOS
- printf("TCG-enabled BIOS.\n");
+ "TCG-enabled"
#endif
- printf("\n");
+ "\n\n");
}
-
//--------------------------------------------------------------------------
// BIOS Boot Specification 1.0.1 compatibility
//
-// Very basic support for the BIOS Boot Specification, which allows expansion
-// ROMs to register themselves as boot devices, instead of just stealing the
+// Very basic support for the BIOS Boot Specification, which allows expansion
+// ROMs to register themselves as boot devices, instead of just stealing the
// INT 19h boot vector.
-//
+//
// This is a hack: to do it properly requires a proper PnP BIOS and we aren't
-// one; we just lie to the option ROMs to make them behave correctly.
-// We also don't support letting option ROMs register as bootable disk
-// drives (BCVs), only as bootable devices (BEVs).
+// one; we just lie to the option ROMs to make them behave correctly.
+// We also don't support letting option ROMs register as bootable disk
+// drives (BCVs), only as bootable devices (BEVs).
//
// http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
//--------------------------------------------------------------------------
-struct ipl_entry {
- Bit16u type;
- Bit16u flags;
- Bit32u vector;
- Bit32u description;
- Bit32u reserved;
-};
+static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
-static void
-init_boot_vectors()
+static void
+init_boot_vectors()
{
- struct ipl_entry e;
+ ipl_entry_t e;
Bit16u count = 0;
Bit16u ss = get_SS();
+ Bit16u ebda_seg = read_word(0x0040, 0x000E);
/* Clear out the IPL table. */
- memsetb(EBDA_SEG, IPL_TABLE_OFFSET, 0, 0xff);
+ memsetb(ebda_seg, IPL_TABLE_OFFSET, 0, IPL_SIZE);
+
+ /* User selected device not set */
+ write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF);
/* Floppy drive */
- e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
- memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
+ e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
+ memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
count++;
/* First HDD */
- e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
- memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
+ e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
+ memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
count++;
#if BX_ELTORITO_BOOT
/* CDROM */
- e.type = 3; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
- memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
+ e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
+ memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
count++;
-#endif
+#endif
/* Remember how many devices we have */
- write_word(EBDA_SEG, IPL_COUNT_OFFSET, count);
+ write_word(ebda_seg, IPL_COUNT_OFFSET, count);
/* Not tried booting anything yet */
- write_word(EBDA_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
+ write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xffff);
}
static Bit8u
get_boot_vector(i, e)
-Bit16u i; struct ipl_entry *e;
+Bit16u i; ipl_entry_t *e;
{
Bit16u count;
Bit16u ss = get_SS();
@@ -2026,22 +2133,107 @@ Bit16u i; struct ipl_entry *e;
return 1;
}
+#if BX_ELTORITO_BOOT
+ void
+interactive_bootkey()
+{
+ ipl_entry_t e;
+ Bit16u count;
+ char description[33];
+ Bit8u scan_code;
+ Bit8u i;
+ Bit16u ss = get_SS();
+ Bit16u valid_choice = 0;
+ Bit16u ebda_seg = read_word(0x0040, 0x000E);
+
+ while (check_for_keystroke())
+ get_keystroke();
+
+ printf("\nPress F12 for boot menu.\n\n");
+
+ delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
+ if (check_for_keystroke())
+ {
+ scan_code = get_keystroke();
+ if (scan_code == 0x86) /* F12 */
+ {
+ while (check_for_keystroke())
+ get_keystroke();
+
+ printf("Select boot device:\n\n");
+
+ count = read_word(ebda_seg, IPL_COUNT_OFFSET);
+ for (i = 0; i < count; i++)
+ {
+ memcpyb(ss, &e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e));
+ printf("%d. ", i+1);
+ switch(e.type)
+ {
+ case IPL_TYPE_FLOPPY:
+ case IPL_TYPE_HARDDISK:
+ case IPL_TYPE_CDROM:
+ printf("%s\n", drivetypes[e.type]);
+ break;
+ case IPL_TYPE_BEV:
+ printf("%s", drivetypes[4]);
+ if (e.description != 0)
+ {
+ memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32);
+ description[32] = 0;
+ printf(" [%S]", ss, description);
+ }
+ printf("\n");
+ break;
+ }
+ }
+
+ count++;
+ while (!valid_choice) {
+ scan_code = get_keystroke();
+ if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
+ {
+ valid_choice = 1;
+ }
+ else if (scan_code <= count)
+ {
+ valid_choice = 1;
+ scan_code -= 1;
+ /* Set user selected device */
+ write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, scan_code);
+ }
+ }
+ printf("\n");
+ }
+ }
+}
+#endif // BX_ELTORITO_BOOT
//--------------------------------------------------------------------------
// print_boot_device
// displays the boot device
//--------------------------------------------------------------------------
-static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
-
void
-print_boot_device(type)
- Bit16u type;
+print_boot_device(e)
+ ipl_entry_t *e;
{
- /* NIC appears as type 0x80 */
- if (type == 0x80 ) type = 0x4;
- if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
- printf("Booting from %s...\n", drivetypes[type]);
+ Bit16u type;
+ char description[33];
+ Bit16u ss = get_SS();
+ type = e->type;
+ /* NIC appears as type 0x80 */
+ if (type == IPL_TYPE_BEV) type = 0x4;
+ if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
+ printf("Booting from %s", drivetypes[type]);
+ /* print product string if BEV */
+ if (type == 4 && e->description != 0) {
+ /* first 32 bytes are significant */
+ memcpyb(ss, &description, (Bit16u)(e->description >> 16), (Bit16u)(e->description & 0xffff), 32);
+ /* terminate string */
+ description[32] = 0;
+ printf(" [%S]", ss, description);
+ }
+ printf("...\n");
}
//--------------------------------------------------------------------------
@@ -2052,17 +2244,17 @@ print_boot_device(type)
print_boot_failure(type, reason)
Bit16u type; Bit8u reason;
{
- if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
+ if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
printf("Boot from %s failed", drivetypes[type]);
if (type < 4) {
/* Report the reason too */
- if (reason==0)
- printf(": not a bootable disk");
- else
- printf(": could not read the boot disk");
+ if (reason==0)
+ printf(": not a bootable disk");
+ else
+ printf(": could not read the boot disk");
}
- printf("\n");
+ printf("\n\n");
}
//--------------------------------------------------------------------------
@@ -2074,220 +2266,10 @@ print_cdromboot_failure( code )
Bit16u code;
{
bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code);
-
- return;
-}
-
-#define WAIT_HZ 18
-/**
- * Check for keystroke.
- * @returns True if keystroke available, False if not.
- */
-Bit8u check_for_keystroke()
-{
-ASM_START
- mov ax, #0x100
- int #0x16
- jz no_key
- mov al, #1
- jmp done
-no_key:
- xor al, al
-done:
-ASM_END
-}
-
-/**
- * Get keystroke.
- * @returns BIOS scan code.
- */
-Bit8u get_keystroke()
-{
-ASM_START
- mov ax, #0x0
- int #0x16
- xchg ah, al
-ASM_END
-}
-/**
- * Waits (sleeps) for the given number of ticks.
- * Checks for keystroke.
- *
- * @returns BIOS scan code if available, 0 if not.
- * @param ticks Number of ticks to sleep.
- * @param stop_on_key Whether to stop immediately upon keypress.
- */
-Bit8u wait(ticks, stop_on_key)
- Bit16u ticks;
- Bit8u stop_on_key;
-{
- long ticks_to_wait, delta;
- Bit32u prev_ticks, t;
- Bit8u scan_code = 0;
-
- /*
- * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
- * We also have to be careful about interrupt storms.
- */
- ticks_to_wait = ticks;
- prev_ticks = read_dword(0x0, 0x46c);
- do
- {
- t = read_dword(0x0, 0x46c);
- if (t > prev_ticks)
- {
- delta = t - prev_ticks; /* The temp var is required or bcc screws up. */
- ticks_to_wait -= delta;
- }
- else if (t < prev_ticks)
- ticks_to_wait -= t; /* wrapped */
- prev_ticks = t;
-
- if (check_for_keystroke())
- {
- scan_code = get_keystroke();
- bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code);
- if (stop_on_key)
- return scan_code;
- }
- } while (ticks_to_wait > 0);
- return scan_code;
-}
-
-static void clearscreen() {
- /* Hide cursor, clear screen and move cursor to starting position */
-ASM_START
- push bx
- push cx
- push dx
-
- mov ax, #0x100
- mov cx, #0x1000
- int #0x10
-
- mov ax, #0x700
- mov bh, #7
- xor cx, cx
- mov dx, #0x184f
- int #0x10
-
- mov ax, #0x200
- xor bx, bx
- xor dx, dx
- int #0x10
-
- pop dx
- pop cx
- pop bx
-ASM_END
-}
-
-int bootmenu(selected)
- int selected;
-{
- Bit8u scode;
- int max;
- Bit16u ebda_seg = read_word(0x0040, 0x000E);
-
- /* get the number of boot devices */
- max = read_word(ebda_seg, IPL_COUNT_OFFSET);
-
- for(;;) {
- if (selected > max || selected < 1) selected = 1;
- clearscreen();
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n");
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " Select boot device\n\n");
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 1. Floppy\n");
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 2. Hard drive\n");
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 3. CD-ROM\n");
- if (max == 4)
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 4. Network\n");
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n Currently selected: %d\n", selected);
-
- do {
- scode = wait(WAIT_HZ, 1);
- } while (scode == 0);
- switch(scode) {
- case 0x02:
- case 0x03:
- case 0x04:
- selected = scode - 1;
- break;
- case 0x05:
- if (max == 4)
- selected = scode -1 ;
- else
- scode = 0;
- break;
- case 0x48:
- selected -= 1;
- if (selected < 1)
- selected = 1;
- scode = 0;
- break;
- case 0x50:
- selected += 1;
- if (selected > max)
- selected = max;
- scode = 0;
- break;
- case 0x1c:
- break;
- default:
- scode = 0;
- break;
- }
- if (scode != 0)
- break;
- }
-
- switch (selected) {
- case 1:
- return 0x3D;
- case 2:
- return 0x3E;
- case 3:
- return 0x3F;
- case 4:
- return 0x58;
- default:
- return 0;
- }
-}
-
-void interactive_bootkey()
-{
- Bit16u i;
- Bit8u scan = 0;
-
- bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO,
- "\n\nPress F10 to select boot device.\n");
-
- scan = wait(1, 0);
- if (scan == 0x44)
- scan = bootmenu(inb_cmos(0x3d) & 0x0f);
-
- /* set the default based on the keypress or menu */
- switch(scan) {
- case 0x3D:
- outb_cmos(0x3d, 0x01);
- break;
- case 0x3E:
- outb_cmos(0x3d, 0x02);
- break;
- case 0x3F:
- outb_cmos(0x3d, 0x03);
- break;
- case 0x58:
- outb_cmos(0x3d, 0x04);
- break;
- default:
- break;
- }
+ return;
}
-
void
nmi_handler_msg()
{
@@ -2306,7 +2288,7 @@ 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_version_string);
+ BX_INFO("%s\n", bios_cvs_version_string);
}
bx_bool
@@ -2341,41 +2323,35 @@ debugger_off()
outb(0xfedc, 0x00);
}
-void
+int
s3_resume()
{
Bit32u s3_wakeup_vector;
- Bit16u s3_wakeup_ip, s3_wakeup_cs;
- Bit8u cmos_shutdown_status;
+ Bit8u s3_resume_flag;
-ASM_START
- push ds
- push ax
- xor ax, ax
- mov ds, ax
- mov ax, word ptr [EBDA_SEG_PTR]
- mov ds, ax
- mov al, [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET]
- mov .s3_resume.cmos_shutdown_status[bp], al
- pop ax
- pop ds
-ASM_END
+ s3_resume_flag = read_byte(0x40, 0xb0);
+#ifdef HVMASSIST
+ s3_wakeup_vector = get_s3_waking_vector();
+#else
+ s3_wakeup_vector = read_dword(0x40, 0xb2);
+#endif
- if (cmos_shutdown_status != CMOS_SHUTDOWN_S3)
- return;
+ BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector);
+ if (s3_resume_flag != CMOS_SHUTDOWN_S3 || !s3_wakeup_vector)
+ return 0;
- s3_wakeup_vector = get_s3_waking_vector();
- if (!s3_wakeup_vector)
- return;
+ write_byte(0x40, 0xb0, 0);
- s3_wakeup_ip = s3_wakeup_vector & 0xF;
- s3_wakeup_cs = s3_wakeup_vector >> 4;
+ /* setup wakeup vector */
+ write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */
+ write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */
+ BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4),
+ (s3_wakeup_vector & 0xF));
ASM_START
- push .s3_resume.s3_wakeup_cs[bp]
- push .s3_resume.s3_wakeup_ip[bp]
- retf
+ jmpf [0x04b6]
ASM_END
+ return 1;
}
#if BX_USE_ATADRV
@@ -2425,6 +2401,7 @@ ASM_END
// bits 7-4 of the device/head (CB_DH) reg
#define ATA_CB_DH_DEV0 0xa0 // select device 0
#define ATA_CB_DH_DEV1 0xb0 // select device 1
+#define ATA_CB_DH_LBA 0x40 // use LBA
// status reg (CB_STAT and CB_ASTAT) bits
#define ATA_CB_STAT_BSY 0x80 // busy
@@ -2474,6 +2451,7 @@ ASM_END
#define ATA_CMD_READ_SECTORS 0x20
#define ATA_CMD_READ_VERIFY_SECTORS 0x40
#define ATA_CMD_RECALIBRATE 0x10
+#define ATA_CMD_REQUEST_SENSE 0x03
#define ATA_CMD_SEEK 0x70
#define ATA_CMD_SET_FEATURES 0xEF
#define ATA_CMD_SET_MULTIPLE_MODE 0xC6
@@ -2518,7 +2496,7 @@ ASM_END
#define ATA_DATA_NO 0x00
#define ATA_DATA_IN 0x01
#define ATA_DATA_OUT 0x02
-
+
// ---------------------------------------------------------------------------
// ATA/ATAPI driver : initialization
// ---------------------------------------------------------------------------
@@ -2527,7 +2505,7 @@ void ata_init( )
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit8u channel, device;
- // Channels info init.
+ // 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);
@@ -2535,7 +2513,7 @@ void ata_init( )
write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
}
- // Devices info init.
+ // 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);
@@ -2550,11 +2528,12 @@ void ata_init( )
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);
+
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
}
- // hdidmap and cdidmap init.
+ // 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);
@@ -2564,6 +2543,58 @@ void ata_init( )
write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
}
+#define TIMEOUT 0
+#define BSY 1
+#define NOT_BSY 2
+#define NOT_BSY_DRQ 3
+#define NOT_BSY_NOT_DRQ 4
+#define NOT_BSY_RDY 5
+
+#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
+
+int await_ide();
+static int await_ide(when_done,base,timeout)
+ Bit8u when_done;
+ Bit16u base;
+ Bit16u timeout;
+{
+ Bit32u time=0,last=0;
+ Bit16u status;
+ Bit8u result;
+ status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw one away
+ for(;;) {
+ status = inb(base+ATA_CB_STAT);
+ time++;
+ if (when_done == BSY)
+ result = status & ATA_CB_STAT_BSY;
+ else if (when_done == NOT_BSY)
+ result = !(status & ATA_CB_STAT_BSY);
+ else if (when_done == NOT_BSY_DRQ)
+ result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
+ else if (when_done == NOT_BSY_NOT_DRQ)
+ result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
+ else if (when_done == NOT_BSY_RDY)
+ result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
+ else if (when_done == TIMEOUT)
+ result = 0;
+
+ if (result) return 0;
+ if (time>>16 != last) // mod 2048 each 16 ms
+ {
+ last = time >>16;
+ BX_DEBUG_ATA("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout);
+ }
+ if (status & ATA_CB_STAT_ERR)
+ {
+ BX_DEBUG_ATA("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout);
+ return -1;
+ }
+ if ((timeout == 0) || ((time>>11) > timeout)) break;
+ }
+ BX_INFO("IDE time out\n");
+ return -1;
+}
+
// ---------------------------------------------------------------------------
// ATA/ATAPI driver : device detection
// ---------------------------------------------------------------------------
@@ -2604,7 +2635,7 @@ void ata_detect( )
// Device detection
hdcount=cdcount=0;
-
+
for(device=0; device<BX_MAX_ATA_DEVICES; device++) {
Bit16u iobase1, iobase2;
Bit8u channel, slave, shift;
@@ -2634,33 +2665,34 @@ void ata_detect( )
if ( (sc == 0x55) && (sn == 0xaa) ) {
write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN);
-
+
// reset the channel
- ata_reset (device);
-
+ 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) ) {
+ 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) ) {
+ 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) ) {
+ } 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
+
+ // Now we send a IDENTIFY command to ATA device
if(type == ATA_TYPE_ATA) {
- Bit32u sectors;
+ Bit32u sectors_low, sectors_high;
Bit16u cylinders, heads, spt, blksize;
Bit8u translation, removable, mode;
@@ -2671,21 +2703,26 @@ void ata_detect( )
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 )
+ if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 )
BX_PANIC("ata-detect: Failed to detect ATA device\n");
removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
-#ifndef NO_PIO32
+#ifndef NO_PIO32
mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
#endif
-
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
+ if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support
+ sectors_low = read_dword(get_SS(),buffer+(100*2)); // word 100 and word 101
+ sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and word 103
+ } else {
+ sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
+ sectors_high = 0;
+ }
write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
@@ -2694,7 +2731,8 @@ void ata_detect( )
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);
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low);
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high);
BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
translation = inb_cmos(0x39 + channel/2);
@@ -2722,14 +2760,14 @@ void ata_detect( )
break;
case ATA_TRANSLATION_LBA:
spt = 63;
- sectors /= 63;
- heads = sectors / 1024;
+ sectors_low /= 63;
+ heads = sectors_low / 1024;
if (heads>128) heads = 255;
else if (heads>64) heads = 128;
else if (heads>32) heads = 64;
else if (heads>16) heads = 32;
else heads=16;
- cylinders = sectors / heads;
+ cylinders = sectors_low / heads;
break;
case ATA_TRANSLATION_RECHS:
// Take care not to overflow
@@ -2756,15 +2794,15 @@ void ata_detect( )
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
+
+ // 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;
@@ -2775,12 +2813,12 @@ void ata_detect( )
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)
+ if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0)
BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
type = read_byte(get_SS(),buffer+1) & 0x1f;
removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
-#ifndef NO_PIO32
+#ifndef NO_PIO32
mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
#endif
blksize = 2048;
@@ -2790,24 +2828,24 @@ void ata_detect( )
write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
- // fill cdidmap
+ // 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;
+ sizeinmb = (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21)
+ | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) >> 11);
case ATA_TYPE_ATAPI:
// Read ATA/ATAPI version
ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
- for(version=15;version>0;version--) {
+ for(version=15;version>0;version--) {
if((ataversion&(1<<version))!=0)
break;
}
@@ -2816,7 +2854,7 @@ void ata_detect( )
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);
@@ -2824,7 +2862,13 @@ void ata_detect( )
if(read_byte(get_SS(),model+i)==0x20)
write_byte(get_SS(),model+i,0x00);
else break;
+ }
+ if (i>36) {
+ write_byte(get_SS(),model+36,0x00);
+ for(i=35;i>32;i--){
+ write_byte(get_SS(),model+i,0x2E);
}
+ }
break;
}
@@ -2832,10 +2876,10 @@ void ata_detect( )
case ATA_TYPE_ATA:
printf("ata%d %s: ",channel,slave?" slave":"master");
i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
- if (sizeinmb < 1UL<<16)
- printf(" ATA-%d Hard-Disk (%04u MBytes)\n",version,(Bit16u)sizeinmb);
- else
- printf(" ATA-%d Hard-Disk (%04u GBytes)\n",version,(Bit16u)(sizeinmb>>10));
+ if (sizeinmb < (1UL<<16))
+ printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb);
+ else
+ printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10));
break;
case ATA_TYPE_ATAPI:
printf("ata%d %s: ",channel,slave?" slave":"master");
@@ -2856,17 +2900,17 @@ void ata_detect( )
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
-
+ // FIXME : move hard_drive_post here
+
}
// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : software reset
+// ATA/ATAPI driver : software reset
// ---------------------------------------------------------------------------
// ATA-3
// 8.2.1 Software reset - Device 0
@@ -2876,7 +2920,8 @@ Bit16u device;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit16u iobase1, iobase2;
- Bit8u channel, slave, sn, sc;
+ Bit8u channel, slave, sn, sc;
+ Bit8u type;
Bit16u max;
channel = device / 2;
@@ -2891,16 +2936,13 @@ Bit16u device;
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;
- }
+ await_ide(BSY, iobase1, 20);
// 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) {
+ type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
+ if (type != ATA_TYPE_NONE) {
// 8.2.1 (g) -- check for sc==sn==0x01
// select device
@@ -2909,21 +2951,14 @@ Bit16u device;
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;
- }
- }
+ if (type == ATA_TYPE_ATA) //ATA
+ await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
+ else //ATAPI
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
}
-// 8.2.1 (i) -- wait for DRDY
- max=0xfff;
- while(--max>0) {
- Bit8u status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_RDY) != 0) break;
+// 8.2.1 (h) -- wait for not BSY
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
}
// Enable interrupts
@@ -2931,7 +2966,7 @@ Bit16u device;
}
// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a non data command
+// ATA/ATAPI driver : execute a non data command
// ---------------------------------------------------------------------------
Bit16u ata_cmd_non_data()
@@ -2949,9 +2984,9 @@ Bit16u ata_cmd_non_data()
// 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 ata_cmd_data_in(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
+Bit32u lba_low, lba_high;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit16u iobase1, iobase2, blksize;
@@ -2980,22 +3015,20 @@ Bit32u lba;
// sector will be 0 only on lba access. Convert to lba-chs
if (sector == 0) {
- if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
+ if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
- outb(iobase1 + ATA_CB_SN, lba >> 24);
- outb(iobase1 + ATA_CB_CL, 0);
- outb(iobase1 + ATA_CB_CH, 0);
+ outb(iobase1 + ATA_CB_SN, lba_low >> 24);
+ outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
+ outb(iobase1 + ATA_CB_CH, lba_high >> 8);
command |= 0x04;
count &= (1UL << 8) - 1;
- lba &= (1UL << 24) - 1;
+ lba_low &= (1UL << 24) - 1;
}
- sector = (Bit16u) (lba & 0x000000ffL);
- lba >>= 8;
- cylinder = (Bit16u) (lba & 0x0000ffffL);
- lba >>= 16;
- head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
- }
+ sector = (Bit16u) (lba_low & 0x000000ffL);
+ cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+ head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+ }
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, count);
@@ -3005,10 +3038,8 @@ Bit32u lba;
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;
- }
+ await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+ status = inb(iobase1 + ATA_CB_STAT);
if (status & ATA_CB_STAT_ERR) {
BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
@@ -3029,12 +3060,12 @@ ASM_END
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]
+ 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 ;;
+ cmp di, #0xf800 ;;
jbe ata_in_no_adjust
ata_in_adjust:
@@ -3046,7 +3077,7 @@ ata_in_no_adjust:
mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port
- mov ah, _ata_cmd_data_in.mode + 2[bp]
+ mov ah, _ata_cmd_data_in.mode + 2[bp]
cmp ah, #ATA_MODE_PIO32
je ata_in_32
@@ -3068,9 +3099,10 @@ ASM_END
current++;
write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
count--;
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
status = inb(iobase1 + ATA_CB_STAT);
if (count == 0) {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ 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;
@@ -3078,7 +3110,7 @@ ASM_END
break;
}
else {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ 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;
@@ -3103,9 +3135,9 @@ ASM_END
// 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 ata_cmd_data_out(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
+Bit32u lba_low, lba_high;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit16u iobase1, iobase2, blksize;
@@ -3134,22 +3166,20 @@ Bit32u lba;
// sector will be 0 only on lba access. Convert to lba-chs
if (sector == 0) {
- if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
+ if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
- outb(iobase1 + ATA_CB_SN, lba >> 24);
- outb(iobase1 + ATA_CB_CL, 0);
- outb(iobase1 + ATA_CB_CH, 0);
+ outb(iobase1 + ATA_CB_SN, lba_low >> 24);
+ outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
+ outb(iobase1 + ATA_CB_CH, lba_high >> 8);
command |= 0x04;
count &= (1UL << 8) - 1;
- lba &= (1UL << 24) - 1;
+ lba_low &= (1UL << 24) - 1;
}
- sector = (Bit16u) (lba & 0x000000ffL);
- lba >>= 8;
- cylinder = (Bit16u) (lba & 0x0000ffffL);
- lba >>= 16;
- head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
- }
+ sector = (Bit16u) (lba_low & 0x000000ffL);
+ cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+ head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+ }
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, count);
@@ -3159,10 +3189,8 @@ Bit32u lba;
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;
- }
+ await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+ status = inb(iobase1 + ATA_CB_STAT);
if (status & ATA_CB_STAT_ERR) {
BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
@@ -3183,12 +3211,12 @@ ASM_END
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]
+ 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 ;;
+ cmp si, #0xf800 ;;
jbe ata_out_no_adjust
ata_out_adjust:
@@ -3200,7 +3228,7 @@ ata_out_no_adjust:
mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port
- mov ah, _ata_cmd_data_out.mode + 2[bp]
+ mov ah, _ata_cmd_data_out.mode + 2[bp]
cmp ah, #ATA_MODE_PIO32
je ata_out_32
@@ -3226,7 +3254,7 @@ ASM_END
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) )
+ 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;
@@ -3234,7 +3262,7 @@ ASM_END
break;
}
else {
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
+ 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;
@@ -3301,19 +3329,17 @@ Bit32u length;
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_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;
- }
+ await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+ status = inb(iobase1 + ATA_CB_STAT);
if (status & ATA_CB_STAT_ERR) {
BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
@@ -3330,13 +3356,13 @@ Bit32u length;
// 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 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
@@ -3349,32 +3375,38 @@ ASM_START
ASM_END
if (inout == ATA_DATA_NO) {
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
status = inb(iobase1 + ATA_CB_STAT);
}
else {
+ Bit16u loops = 0;
+ Bit8u sc;
while (1) {
+ if (loops == 0) {//first time through
+ status = inb(iobase2 + ATA_CB_ASTAT);
+ await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+ }
+ else
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
+ loops++;
+
status = inb(iobase1 + ATA_CB_STAT);
+ sc = inb(iobase1 + ATA_CB_SC);
// Check if command completed
- if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break;
+ if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
+ ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) break;
if (status & ATA_CB_STAT_ERR) {
BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
return 3;
}
- // 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);
@@ -3435,10 +3467,10 @@ ASM_START
mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port
- mov cx, _ata_cmd_packet.lbefore + 2[bp]
+ mov cx, _ata_cmd_packet.lbefore + 2[bp]
jcxz ata_packet_no_before
- mov ah, _ata_cmd_packet.lmode + 2[bp]
+ mov ah, _ata_cmd_packet.lmode + 2[bp]
cmp ah, #ATA_MODE_PIO32
je ata_packet_in_before_32
@@ -3455,14 +3487,14 @@ ata_packet_in_before_32_loop:
pop eax
ata_packet_no_before:
- mov cx, _ata_cmd_packet.lcount + 2[bp]
+ 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 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]
+ mov ah, _ata_cmd_packet.lmode + 2[bp]
cmp ah, #ATA_MODE_PIO32
je ata_packet_in_32
@@ -3476,10 +3508,10 @@ ata_packet_in_32:
insd ;; CX dwords transfered to port(DX) to ES:[DI]
ata_packet_after:
- mov cx, _ata_cmd_packet.lafter + 2[bp]
+ mov cx, _ata_cmd_packet.lafter + 2[bp]
jcxz ata_packet_done
- mov ah, _ata_cmd_packet.lmode + 2[bp]
+ mov ah, _ata_cmd_packet.lmode + 2[bp]
cmp ah, #ATA_MODE_PIO32
je ata_packet_in_after_32
@@ -3509,7 +3541,7 @@ ASM_END
}
// 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) )
+ 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;
@@ -3528,55 +3560,108 @@ ASM_END
// Start of ATA/ATAPI generic functions
// ---------------------------------------------------------------------------
- Bit16u
-atapi_get_sense(device)
+ Bit16u
+atapi_get_sense(device, seg, asc, ascq)
Bit16u device;
{
Bit8u atacmd[12];
- Bit8u buffer[16];
+ Bit8u buffer[18];
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)
+ // Request SENSE
+ atacmd[0]=ATA_CMD_REQUEST_SENSE;
+ atacmd[4]=sizeof(buffer);
+ if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, get_SS(), buffer) != 0)
return 0x0002;
- if ((buffer[0] & 0x7e) == 0x70) {
- return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12];
- }
+ write_byte(seg,asc,buffer[12]);
+ write_byte(seg,ascq,buffer[13]);
return 0;
}
- Bit16u
+ Bit16u
atapi_is_ready(device)
Bit16u device;
{
- Bit8u atacmd[12];
- Bit8u buffer[];
+ Bit8u packet[12];
+ Bit8u buf[8];
+ Bit32u block_len;
+ Bit32u sectors;
+ Bit32u timeout; //measured in ms
+ Bit32u time;
+ Bit8u asc, ascq;
+ Bit8u in_progress;
+ Bit16u ebda_seg = read_word(0x0040,0x000E);
+ if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI) {
+ printf("not implemented for non-ATAPI device\n");
+ return -1;
+ }
- 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;
+ BX_DEBUG_ATA("ata_detect_medium: begin\n");
+ memsetb(get_SS(),packet, 0, sizeof packet);
+ packet[0] = 0x25; /* READ CAPACITY */
+
+ /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT
+ * is reported by the device. If the device reports "IN PROGRESS",
+ * 30 seconds is added. */
+ timeout = 5000;
+ time = 0;
+ in_progress = 0;
+ while (time < timeout) {
+ if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L, ATA_DATA_IN, get_SS(), buf) == 0)
+ goto ok;
+
+ if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) {
+ if (asc == 0x3a) { /* MEDIUM NOT PRESENT */
+ BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n");
+ return -1;
+ }
- if (atapi_get_sense(device) !=0 ) {
- memsetb(get_SS(),atacmd,0,12);
+ if (asc == 0x04 && ascq == 0x01 && !in_progress) {
+ /* IN PROGRESS OF BECOMING READY */
+ printf("Waiting for device to detect medium... ");
+ /* Allow 30 seconds more */
+ timeout = 30000;
+ in_progress = 1;
+ }
+ }
+ time += 100;
+ }
+ BX_DEBUG_ATA("read capacity failed\n");
+ return -1;
+ok:
- // 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;
+ block_len = (Bit32u) buf[4] << 24
+ | (Bit32u) buf[5] << 16
+ | (Bit32u) buf[6] << 8
+ | (Bit32u) buf[7] << 0;
+ BX_DEBUG_ATA("block_len=%u\n", block_len);
- return atapi_get_sense(device);
- }
+ if (block_len!= 2048 && block_len!= 512)
+ {
+ printf("Unsupported sector size %u\n", block_len);
+ return -1;
+ }
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].blksize, block_len);
+
+ sectors = (Bit32u) buf[0] << 24
+ | (Bit32u) buf[1] << 16
+ | (Bit32u) buf[2] << 8
+ | (Bit32u) buf[3] << 0;
+
+ BX_DEBUG_ATA("sectors=%u\n", sectors);
+ if (block_len == 2048)
+ sectors <<= 2; /* # of sectors in 512-byte "soft" sector */
+ if (sectors != read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low))
+ printf("%dMB medium detected\n", sectors>>(20-9));
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);
return 0;
}
- Bit16u
+ Bit16u
atapi_is_cdrom(device)
Bit8u device;
{
@@ -3636,7 +3721,7 @@ static char eltorito[24]="EL TORITO SPECIFICATION";
//
// Returns ah: emulated drive, al: error code
//
- Bit16u
+ Bit16u
cdrom_boot()
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
@@ -3649,10 +3734,13 @@ cdrom_boot()
for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
if (atapi_is_cdrom(device)) break;
}
-
+
// if not found
if(device >= BX_MAX_ATA_DEVICES) return 2;
+ if(error = atapi_is_ready(device) != 0)
+ BX_INFO("ata_is_ready returned %d\n",error);
+
// Read the Boot Record Volume Descriptor
memsetb(get_SS(),atacmd,0,12);
atacmd[0]=0x28; // READ command
@@ -3672,7 +3760,7 @@ cdrom_boot()
}
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];
@@ -3687,7 +3775,7 @@ cdrom_boot()
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
@@ -3706,10 +3794,10 @@ cdrom_boot()
write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]);
if(buffer[0x21]==0){
- // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
+ // 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
@@ -3723,7 +3811,7 @@ cdrom_boot()
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);
@@ -3748,7 +3836,6 @@ cdrom_boot()
tcpa_ipl((Bit32u)1L,(Bit32u)boot_segment,(Bit32u)0L,(Bit32u)512L);
#endif
-
// Remember the media type
switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
case 0x01: // 1.2M floppy
@@ -3769,7 +3856,7 @@ cdrom_boot()
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);
+ (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;
}
@@ -3782,7 +3869,7 @@ cdrom_boot()
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);
@@ -4128,9 +4215,10 @@ ASM_END
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;
+ // According to Ralf Brown's interrupt the limit should be 15M,
+ // but real machines mostly return max. 63M.
+ if(regs.u.r16.ax > 0xffc0)
+ regs.u.r16.ax = 0xffc0;
CLEAR_CF();
#endif
@@ -4348,13 +4436,35 @@ BX_DEBUG_INT15("case 2:\n");
case 3: // Set Resolution
BX_DEBUG_INT15("case 3:\n");
- // BX:
+ // BH:
// 0 = 25 dpi, 1 count per millimeter
// 1 = 50 dpi, 2 counts per millimeter
// 2 = 100 dpi, 4 counts per millimeter
// 3 = 200 dpi, 8 counts per millimeter
- CLEAR_CF();
- regs.u.r8.ah = 0;
+ comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
+ if (regs.u.r8.bh < 4) {
+ ret = send_to_mouse_ctrl(0xE8); // set resolution command
+ if (ret == 0) {
+ ret = get_mouse_data(&mouse_data1);
+ if (mouse_data1 != 0xfa)
+ BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
+ ret = send_to_mouse_ctrl(regs.u.r8.bh);
+ ret = get_mouse_data(&mouse_data1);
+ if (mouse_data1 != 0xfa)
+ BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
+ CLEAR_CF();
+ regs.u.r8.ah = 0;
+ } else {
+ // error
+ SET_CF();
+ regs.u.r8.ah = UNSUPPORTED_FUNCTION;
+ }
+ } else {
+ // error
+ SET_CF();
+ regs.u.r8.ah = UNSUPPORTED_FUNCTION;
+ }
+ set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
break;
case 4: // Get Device ID
@@ -4476,7 +4586,30 @@ BX_DEBUG_INT15("case default:\n");
break;
}
}
-#endif
+#endif // BX_USE_PS2_MOUSE
+
+
+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)
@@ -4490,17 +4623,20 @@ 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
+ // 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 ax, .int15_function32.CX [bp]
+ mov bx, sp
+ mov ax, _int15_function32.CX [bx]
shl eax, #16
- mov ax, .int15_function32.DX [bp]
+ mov ax, _int15_function32.DX [bx]
;; convert to numbers of 15usec ticks
mov ebx, #15
@@ -4531,7 +4667,8 @@ ASM_END
case 0xe8:
switch(regs.u.r8.al)
{
- case 0x20: {
+#ifdef HVMASSIST
+ case 0x20: {
Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
if (regs.u.r32.edx != 0x534D4150) /* SMAP */
@@ -4579,7 +4716,7 @@ ASM_END
// 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 > (15*1024))
regs.u.r16.cx = 15*1024;
@@ -4607,7 +4744,7 @@ ASM_END
regs.u.r16.bx = regs.u.r16.dx;
break;
}
- default: /* AH=0xE8?? but not implemented */
+ default: /* AH=0xE8?? but not implemented */
goto int15_unimplemented;
}
break;
@@ -4620,17 +4757,179 @@ ASM_END
regs.u.r8.ah = UNSUPPORTED_FUNCTION;
break;
}
+#else
+ case 0x20: // coded by osmaker aka K.J.
+ if(regs.u.r32.edx == 0x534D4150)
+ {
+ extended_memory_size = inb_cmos(0x35);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x34);
+ extended_memory_size *= 64;
+ // greater than EFF00000???
+ if(extended_memory_size > 0x3bc000) {
+ extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
+ }
+ extended_memory_size *= 1024;
+ extended_memory_size += (16L * 1024 * 1024);
+
+ if(extended_memory_size <= (16L * 1024 * 1024)) {
+ extended_memory_size = inb_cmos(0x31);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x30);
+ extended_memory_size *= 1024;
+ extended_memory_size += (1L * 1024 * 1024);
+ }
+
+ switch(regs.u.r16.bx)
+ {
+ case 0:
+ set_e820_range(ES, regs.u.r16.di,
+ 0x0000000L, 0x0009f000L, 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,
+ 0x0009f000L, 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:
+#if BX_ROMBIOS32
+ set_e820_range(ES, regs.u.r16.di,
+ 0x00100000L,
+ extended_memory_size - ACPI_DATA_SIZE, 1);
+ regs.u.r32.ebx = 4;
+#else
+ set_e820_range(ES, regs.u.r16.di,
+ 0x00100000L,
+ extended_memory_size, 1);
+ regs.u.r32.ebx = 5;
+#endif
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ break;
+ case 4:
+ set_e820_range(ES, regs.u.r16.di,
+ extended_memory_size - ACPI_DATA_SIZE,
+ extended_memory_size, 3); // ACPI RAM
+ regs.u.r32.ebx = 5;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ break;
+ case 5:
+ /* 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;
+ }
+#endif /* HVMASSIST */
}
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;
+ Bit8u scan_code, ascii_code, shift_flags, led_flags, count;
Bit16u kbd_code, max;
BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
+ shift_flags = read_byte(0x0040, 0x17);
+ led_flags = read_byte(0x0040, 0x97);
+ if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) {
+ASM_START
+ cli
+ASM_END
+ outb(0x60, 0xed);
+ while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
+ if ((inb(0x60) == 0xfa)) {
+ led_flags &= 0xf8;
+ led_flags |= ((shift_flags >> 4) & 0x07);
+ outb(0x60, led_flags & 0x07);
+ while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
+ inb(0x60);
+ write_byte(0x0040, 0x97, led_flags);
+ }
+ASM_START
+ sti
+ASM_END
+ }
+
switch (GET_AH()) {
case 0x00: /* read keyboard input */
@@ -4668,7 +4967,7 @@ int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
break;
case 0x09: /* GET KEYBOARD FUNCTIONALITY */
- // bit Bochs Description
+ // 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)
@@ -4698,7 +4997,7 @@ int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
kbd_code |= (inb(0x60) << 8);
}
} while (--count>0);
- }
+ }
}
BX=kbd_code;
break;
@@ -4725,7 +5024,8 @@ int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
case 0x12: /* get extended keyboard status */
shift_flags = read_byte(0x0040, 0x17);
SET_AL(shift_flags);
- shift_flags = read_byte(0x0040, 0x18);
+ 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;
@@ -4740,7 +5040,7 @@ int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
case 0x6F:
if (GET_AL() == 0x08)
- SET_AH(0x02); // unsupported, aka normal keyboard
+ SET_AH(0x02); // unsupported, aka normal keyboard
default:
BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
@@ -4881,7 +5181,7 @@ 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;
+ Bit8u mf2_flags, mf2_state;
//
// DS has been set to F000 before call
@@ -4899,7 +5199,6 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
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) {
@@ -4908,8 +5207,6 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
write_byte(0x0040, 0x17, shift_flags);
mf2_flags |= 0x40;
write_byte(0x0040, 0x18, mf2_flags);
- led_flags ^= 0x04;
- write_byte(0x0040, 0x97, led_flags);
break;
case 0xba: /* Caps Lock release */
mf2_flags &= ~0x40;
@@ -4917,11 +5214,8 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
break;
case 0x2a: /* L Shift press */
- /*shift_flags &= ~0x40;*/
shift_flags |= 0x02;
write_byte(0x0040, 0x17, shift_flags);
- led_flags &= ~0x04;
- write_byte(0x0040, 0x97, led_flags);
break;
case 0xaa: /* L Shift release */
shift_flags &= ~0x02;
@@ -4929,11 +5223,8 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
break;
case 0x36: /* R Shift press */
- /*shift_flags &= ~0x40;*/
shift_flags |= 0x01;
write_byte(0x0040, 0x17, shift_flags);
- led_flags &= ~0x04;
- write_byte(0x0040, 0x97, led_flags);
break;
case 0xb6: /* R Shift release */
shift_flags &= ~0x01;
@@ -4941,71 +5232,75 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
break;
case 0x1d: /* Ctrl press */
- shift_flags |= 0x04;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x01) {
- mf2_flags |= 0x04;
- } else {
- mf2_flags |= 0x01;
+ 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);
}
- write_byte(0x0040, 0x18, mf2_flags);
+ }
break;
case 0x9d: /* Ctrl release */
- shift_flags &= ~0x04;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x01) {
- mf2_flags &= ~0x04;
- } else {
- mf2_flags &= ~0x01;
+ 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);
}
- write_byte(0x0040, 0x18, mf2_flags);
+ }
break;
case 0x38: /* Alt press */
shift_flags |= 0x08;
write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x01) {
- mf2_flags |= 0x08;
+ if (mf2_state & 0x02) {
+ mf2_state |= 0x08;
+ write_byte(0x0040, 0x96, mf2_state);
} else {
mf2_flags |= 0x02;
- }
- write_byte(0x0040, 0x18, mf2_flags);
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
break;
case 0xb8: /* Alt release */
shift_flags &= ~0x08;
write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x01) {
- mf2_flags &= ~0x08;
+ if (mf2_state & 0x02) {
+ mf2_state &= ~0x08;
+ write_byte(0x0040, 0x96, mf2_state);
} else {
mf2_flags &= ~0x02;
- }
- write_byte(0x0040, 0x18, mf2_flags);
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
break;
case 0x45: /* Num Lock press */
- if ((mf2_state & 0x01) == 0) {
+ 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 & 0x01) == 0) {
+ 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 */
@@ -5018,50 +5313,55 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
machine_reset();
/* Fall through */
default:
- if (scancode & 0x80) return; /* toss key releases ... */
+ if (scancode & 0x80) {
+ break; /* toss key releases ... */
+ }
if (scancode > MAX_SCAN_CODE) {
- BX_INFO("KBD: int09h_handler(): unknown scancode (%x) read!\n", scancode);
+ 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 */
+ } 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
+ } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) {
+ /* extended keys handling */
+ asciicode = 0xe0;
+ scancode = scan_to_scanascii[scancode].normal >> 8;
+ } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
+ /* check if lock state should be ignored
* because a SHIFT key are pressed */
-
+
if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
asciicode = scan_to_scanascii[scancode].normal;
scancode = scan_to_scanascii[scancode].normal >> 8;
- }
- else {
+ } else {
asciicode = scan_to_scanascii[scancode].shift;
scancode = scan_to_scanascii[scancode].shift >> 8;
- }
}
- else {
+ } 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 {
+ } 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;
- }
- mf2_state &= ~0x01;
+ }
+ if ((scancode & 0x7f) != 0x1d) {
+ mf2_state &= ~0x01;
+ }
+ mf2_state &= ~0x02;
+ write_byte(0x0040, 0x96, mf2_state);
}
unsigned int
@@ -5070,9 +5370,6 @@ enqueue_key(scan_code, ascii_code)
{
Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail;
- //BX_INFO("KBD: enqueue_key() called scan:%02x, ascii:%02x\n",
- // scan_code, ascii_code);
-
#if BX_CPU < 2
buffer_start = 0x001E;
buffer_end = 0x003E;
@@ -5122,9 +5419,8 @@ BX_DEBUG_INT74("int74: read byte %02x\n", in_byte);
mouse_flags_2 = read_byte(ebda_seg, 0x0027);
if ( (mouse_flags_2 & 0x80) != 0x80 ) {
- // BX_PANIC("int74_function:\n");
return;
- }
+ }
package_count = mouse_flags_2 & 0x07;
index = mouse_flags_1 & 0x07;
@@ -5152,10 +5448,10 @@ BX_DEBUG_INT74("int74_function: make_farcall=1\n");
#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;
+int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
- Bit32u lba;
+ Bit32u lba_low, lba_high;
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit16u cylinder, head, sector;
Bit16u segment, offset;
@@ -5176,12 +5472,12 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
// Get the ata channel
device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
- // basic check : device has to be valid
+ // 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 */
@@ -5199,7 +5495,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
break;
case 0x02: // read disk sectors
- case 0x03: // write disk sectors
+ case 0x03: // write disk sectors
case 0x04: // verify disk sectors
count = GET_AL();
@@ -5211,10 +5507,10 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
segment = ES;
offset = BX;
- if ( (count > 128) || (count == 0) ) {
- BX_INFO("int13_harddisk: function %02x, count out of range!\n",GET_AH());
+ if ((count > 128) || (count == 0) || (sector == 0)) {
+ BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH());
goto int13_fail;
- }
+ }
nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
@@ -5225,7 +5521,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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;
@@ -5234,14 +5530,15 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
// 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;
+ lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
+ lba_high = 0;
sector = 0; // this forces the command to be lba
}
if ( GET_AH() == 0x02 )
- status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba, segment, offset);
+ status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
else
- status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, segment, offset);
+ status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
// Set nb of sector transferred
SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
@@ -5262,7 +5559,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
@@ -5277,13 +5574,13 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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 ) {
@@ -5297,15 +5594,15 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
+ // Get logical geometry from table
+ nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
+ nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
+ nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
// Compute sector count seen by int13
- lba = (Bit32u)(npc - 1) * (Bit32u)nph * (Bit32u)npspt;
- CX = lba >> 16;
- DX = lba & 0xffff;
+ lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt;
+ CX = lba_low >> 16;
+ DX = lba_low & 0xffff;
SET_AH(3); // hard disk accessible
goto int13_success_noah;
@@ -5326,17 +5623,18 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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());
+
+ // Get 32 msb lba and check
+ lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
+ if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) {
+ BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
goto int13_fail;
}
- // Get 32 bits lba and check
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
- if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) {
+ // Get 32 lsb lba and check
+ lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
+ if (lba_high == read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high)
+ && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) {
BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
goto int13_fail;
}
@@ -5344,12 +5642,12 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
// 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);
+ status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
else
- status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset);
+ status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
@@ -5367,7 +5665,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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
@@ -5377,7 +5675,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
size=read_word(DS,SI+(Bit16u)&Int13DPT->size);
// Buffer is too small
- if(size < 0x1a)
+ if(size < 0x1a)
goto int13_fail;
// EDD 1.x
@@ -5387,17 +5685,26 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
+ lba_low = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low);
+ lba_high = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high);
blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
- write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
- write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
+ if (lba_high || (lba_low/npspt)/nph > 0x3fff)
+ {
+ write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is invalid
+ write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff);
+ }
+ else
+ {
+ write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
+ write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
+ }
write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba); // FIXME should be Bit64
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);
- write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high);
+ write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
}
// EDD 2.x
@@ -5407,8 +5714,8 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
+ 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;
@@ -5418,14 +5725,14 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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 = (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);
+ 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_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
@@ -5434,10 +5741,13 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
-
+ if (size >=0x42)
+ write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
+ else
+ write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10);
+
checksum=0;
- for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i);
+ for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
checksum = ~checksum;
write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
}
@@ -5463,7 +5773,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
}
- else {
+ else {
// FIXME PCI
}
write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
@@ -5476,7 +5786,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
}
- else {
+ else {
// FIXME PCI
}
write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
@@ -5512,7 +5822,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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());
+ BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH());
goto int13_success;
break;
@@ -5521,7 +5831,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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());
+ BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
goto int13_fail;
break;
}
@@ -5557,8 +5867,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
- // BX_DEBUG_INT13_CD("int13_cdrom: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI);
-
+
SET_DISK_RET_STATUS(0x00);
/* basic check : device should be 0xE0+ */
@@ -5575,16 +5884,16 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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 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;
@@ -5606,7 +5915,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
/* set CF if error status read */
if (status) goto int13_fail_nostatus;
else goto int13_success_noah;
- break;
+ break;
case 0x15: /* read disk drive size */
SET_AH(0x02);
@@ -5623,11 +5932,11 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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) {
@@ -5635,13 +5944,13 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
goto int13_fail;
}
- // Get 32 bits lba
+ // 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
@@ -5650,7 +5959,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
+ 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);
@@ -5697,21 +6006,21 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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
+ int #0x15
mov _int13_cdrom.status + 2[bp], ah
jnc int13_cdrom_rme_end
mov _int13_cdrom.status, #1
@@ -5731,7 +6040,7 @@ int13_cdrom_rme_end:
size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
// Buffer is too small
- if(size < 0x1a)
+ if(size < 0x1a)
goto int13_fail;
// EDD 1.x
@@ -5746,8 +6055,8 @@ int13_cdrom_rme_end:
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);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
+ write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
}
// EDD 2.x
@@ -5757,8 +6066,8 @@ int13_cdrom_rme_end:
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);
+ 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;
@@ -5774,7 +6083,7 @@ int13_cdrom_rme_end:
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_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
@@ -5786,7 +6095,7 @@ int13_cdrom_rme_end:
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);
+ for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
checksum = ~checksum;
write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
}
@@ -5812,7 +6121,7 @@ int13_cdrom_rme_end:
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
}
- else {
+ else {
// FIXME PCI
}
write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
@@ -5825,7 +6134,7 @@ int13_cdrom_rme_end:
write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
}
- else {
+ else {
// FIXME PCI
}
write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
@@ -5847,7 +6156,7 @@ int13_cdrom_rme_end:
SET_AH(06);
goto int13_fail_nostatus;
break;
-
+
case 0x4e: // // IBM/MS set hardware configuration
// DMA, prefetch, PIO maximum not supported
switch (GET_AL()) {
@@ -5909,7 +6218,7 @@ int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
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
@@ -5984,11 +6293,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
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);
- //BX_DEBUG_INT13_ET("int13_cdemu: SS=%04x ES=%04x DI=%04x SI=%04x\n", get_SS(), ES, DI, SI);
-
+
/* at this point, we are emulating a floppy/harddisk */
-
- // Recompute the device number
+
+ // Recompute the device number
device = read_byte(ebda_seg,&EbdaData->cdemu.controller_index) * 2;
device += read_byte(ebda_seg,&EbdaData->cdemu.device_spec);
@@ -6001,7 +6309,6 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
goto int13_fail;
}
-
switch (GET_AH()) {
// all those functions return SUCCESS
@@ -6010,7 +6317,7 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
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 0x11: /* recalibrate */
case 0x14: /* controller internal diagnostic */
case 0x16: /* detect disk change */
goto int13_success;
@@ -6035,9 +6342,9 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
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);
+ 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);
@@ -6066,17 +6373,17 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
// 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;
+ 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
@@ -6096,10 +6403,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
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;
-
+ 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 );
@@ -6107,7 +6414,7 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
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;
@@ -6143,7 +6450,7 @@ ASM_END
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 0x48: // IBM/MS get drive parameters
case 0x49: // IBM/MS extended media change
case 0x4e: // ? - set hardware configuration
case 0x50: // ? - send packet command
@@ -6231,8 +6538,8 @@ 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;
+int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit8u drive, num_sectors, sector, head, status, mod;
Bit8u drive_map;
@@ -6338,7 +6645,7 @@ BX_DEBUG_INT13_HD("int13_f01\n");
}
if ( (num_sectors > 128) || (num_sectors == 0) )
- BX_PANIC("int13_harddisk(): num_sectors out of range!\n");
+ BX_PANIC("int13_harddisk: num_sectors out of range!\n");
if (head > 15)
BX_PANIC("hard drive BIOS:(read/verify) head > 15\n");
@@ -6484,7 +6791,7 @@ BX_DEBUG_INT13_HD("int13_f03\n");
}
if ( (num_sectors > 128) || (num_sectors == 0) )
- BX_PANIC("int13_harddisk(): num_sectors out of range!\n");
+ BX_PANIC("int13_harddisk: num_sectors out of range!\n");
if (head > 15)
BX_PANIC("hard drive BIOS:(read) head > 15\n");
@@ -6594,7 +6901,7 @@ BX_DEBUG_INT13_HD("int13_f05\n");
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);
@@ -6734,10 +7041,10 @@ ASM_END
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 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
@@ -6782,7 +7089,7 @@ get_hd_geometry(drive, hd_cylinders, hd_heads, hd_sectors)
hd_type = inb_cmos(0x12) & 0x0f;
if (hd_type != 0x0f)
BX_INFO(panic_msg_reg12h,1);
- hd_type = inb_cmos(0x1a); // HD0: extended type
+ hd_type = inb_cmos(0x1a); // HD1: extended type
if (hd_type != 47)
BX_INFO(panic_msg_reg19h,0,0x1a);
iobase = 0x24;
@@ -6801,11 +7108,72 @@ get_hd_geometry(drive, hd_cylinders, hd_heads, hd_sectors)
#endif //else BX_USE_ATADRV
+#if BX_SUPPORT_FLOPPY
//////////////////////
// FLOPPY functions //
//////////////////////
+void floppy_reset_controller()
+{
+ Bit8u val8;
+
+ // Reset controller
+ val8 = inb(0x03f2);
+ outb(0x03f2, val8 & ~0x04);
+ outb(0x03f2, val8 | 0x04);
+
+ // Wait for controller to come out of reset
+ do {
+ val8 = inb(0x3f4);
+ } while ( (val8 & 0xc0) != 0x80 );
+}
+
+void floppy_prepare_controller(drive)
+ Bit16u drive;
+{
+ Bit8u val8, dor, prev_reset;
+
+ // set 40:3e bit 7 to 0
+ val8 = read_byte(0x0040, 0x003e);
+ val8 &= 0x7f;
+ write_byte(0x0040, 0x003e, val8);
+
+ // turn on motor of selected drive, DMA & int enabled, normal operation
+ prev_reset = inb(0x03f2) & 0x04;
+ if (drive)
+ dor = 0x20;
+ else
+ dor = 0x10;
+ dor |= 0x0c;
+ dor |= drive;
+ outb(0x03f2, dor);
+
+ // reset the disk motor timeout value of INT 08
+ write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
+
+ // wait for drive readiness
+ do {
+ val8 = inb(0x3f4);
+ } while ( (val8 & 0xc0) != 0x80 );
+
+ if (prev_reset == 0) {
+ // turn on interrupts
+ASM_START
+ sti
+ASM_END
+ // wait on 40:3e bit 7 to become 1
+ do {
+ val8 = read_byte(0x0040, 0x003e);
+ } while ( (val8 & 0x80) == 0 );
+ val8 &= 0x7f;
+ASM_START
+ cli
+ASM_END
+ write_byte(0x0040, 0x003e, val8);
+ }
+}
+
bx_bool
floppy_media_known(drive)
Bit16u drive;
@@ -6912,7 +7280,7 @@ floppy_media_sense(drive)
retval = 1;
}
//
- // Extended floppy size uses special cmos setting
+ // Extended floppy size uses special cmos setting
else if ( drive_type == 6 ) {
// 160k 5.25" drive
config_data = 0x00; // 0000 0000
@@ -6953,63 +7321,41 @@ floppy_media_sense(drive)
floppy_drive_recal(drive)
Bit16u drive;
{
- Bit8u val8, dor;
+ Bit8u val8;
Bit16u curr_cyl_offset;
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0000, 0x043e);
- val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
-
- // turn on motor of selected drive, DMA & int enabled, normal operation
- 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);
-
- // check port 3f4 for drive readiness
- val8 = inb(0x3f4);
- if ( (val8 & 0xf0) != 0x80 )
- BX_PANIC("floppy recal:f07: ctrl not ready\n");
+ 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
+ // turn on interrupts
ASM_START
sti
ASM_END
// wait on 40:3e bit 7 to become 1
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
- while ( val8 == 0 ) {
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
- }
+ do {
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
+ 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(0x0000, 0x043e);
+ val8 = read_byte(0x0040, 0x003e);
val8 &= 0x7f;
if (drive) {
val8 |= 0x02; // Drive 1 calibrated
curr_cyl_offset = 0x0095;
- }
- else {
+ } 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
@@ -7036,7 +7382,6 @@ floppy_drive_exists(drive)
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;
@@ -7049,7 +7394,6 @@ int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
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);
- // BX_DEBUG_INT13_FL("int13_diskette: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), get_DS(), ES, DI, SI);
ah = GET_AH();
@@ -7062,7 +7406,7 @@ BX_DEBUG_INT13_FL("floppy f00\n");
set_diskette_ret_status(1);
SET_CF();
return;
- }
+ }
drive_type = inb_cmos(0x10);
if (drive == 0)
@@ -7074,7 +7418,7 @@ BX_DEBUG_INT13_FL("floppy f00\n");
set_diskette_ret_status(0x80);
SET_CF();
return;
- }
+ }
SET_AH(0);
set_diskette_ret_status(0);
CLEAR_CF(); // successful
@@ -7087,7 +7431,7 @@ BX_DEBUG_INT13_FL("floppy f00\n");
SET_AH(val8);
if (val8) {
SET_CF();
- }
+ }
return;
case 0x02: // Read Diskette Sectors
@@ -7099,15 +7443,15 @@ BX_DEBUG_INT13_FL("floppy f00\n");
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");
+ if ((drive > 1) || (head > 1) || (sector == 0) ||
+ (num_sectors == 0) || (num_sectors > 72)) {
+ BX_INFO("int13_diskette: read/write/verify: parameter out of range\n");
SET_AH(1);
set_diskette_ret_status(1);
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
+ }
// see if drive exists
if (floppy_drive_exists(drive) == 0) {
@@ -7116,7 +7460,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
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) {
@@ -7126,8 +7470,8 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
}
+ }
if (ah == 0x02) {
// Read Diskette Sectors
@@ -7146,7 +7490,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
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
@@ -7157,7 +7501,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
+ }
BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
outb(0x000a, 0x06);
@@ -7190,28 +7534,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
//--------------------------------------
// set up floppy controller for transfer
//--------------------------------------
-
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0000, 0x043e);
- val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
-
- // turn on motor of selected drive, DMA & int enabled, normal operation
- 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);
-
- // check port 3f4 for drive readiness
- val8 = inb(0x3f4);
- if ( (val8 & 0xf0) != 0x80 )
- BX_PANIC("int13_diskette:f02: ctrl not ready\n");
+ floppy_prepare_controller(drive);
// send read-normal-data command (9 bytes) to controller
outb(0x03f5, 0xe6); // e6: read normal data
@@ -7224,27 +7547,35 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
outb(0x03f5, 0); // Gap length
outb(0x03f5, 0xff); // Gap length
- // turn on interrupts
+ // turn on interrupts
ASM_START
sti
ASM_END
// wait on 40:3e bit 7 to become 1
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
- while ( val8 == 0 ) {
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
+ 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
+ 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(0x0000, 0x043e);
+ val8 = read_byte(0x0040, 0x003e);
val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
+ write_byte(0x0040, 0x003e, val8);
// check port 3f4 for accessibility to status bytes
val8 = inb(0x3f4);
@@ -7275,7 +7606,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
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);
@@ -7283,8 +7614,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
SET_AH(0x00); // success
CLEAR_CF(); // success
return;
- }
- else if (ah == 0x03) {
+ } else if (ah == 0x03) {
// Write Diskette Sectors
//-----------------------------------
@@ -7301,7 +7631,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
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
@@ -7312,7 +7642,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
+ }
BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
outb(0x000a, 0x06);
@@ -7338,30 +7668,9 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
//--------------------------------------
// set up floppy controller for transfer
//--------------------------------------
+ floppy_prepare_controller(drive);
- // set 40:3e bit 7 to 0
- val8 = read_byte(0x0000, 0x043e);
- val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
-
- // turn on motor of selected drive, DMA & int enabled, normal operation
- 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);
-
- // check port 3f4 for drive readiness
- val8 = inb(0x3f4);
- if ( (val8 & 0xf0) != 0x80 )
- BX_PANIC("int13_diskette:f03: ctrl not ready\n");
-
- // send read-normal-data command (9 bytes) to controller
+ // 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);
@@ -7372,27 +7681,35 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
outb(0x03f5, 0); // Gap length
outb(0x03f5, 0xff); // Gap length
- // turn on interrupts
+ // turn on interrupts
ASM_START
sti
ASM_END
// wait on 40:3e bit 7 to become 1
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
- while ( val8 == 0 ) {
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
+ 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
+ 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(0x0000, 0x043e);
+ val8 = read_byte(0x0040, 0x003e);
val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
+ write_byte(0x0040, 0x003e, val8);
// check port 3f4 for accessibility to status bytes
val8 = inb(0x3f4);
@@ -7436,8 +7753,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
SET_AH(0x00); // success
CLEAR_CF(); // success
return;
- }
- else { // if (ah == 0x04)
+ } else { // if (ah == 0x04)
// Verify Diskette Sectors
// ??? should track be new val from return_status[3] ?
@@ -7446,8 +7762,8 @@ BX_INFO("floppy: drive>1 || head>1 ...\n");
CLEAR_CF(); // success
SET_AH(0x00); // success
return;
- }
-
+ }
+ break;
case 0x05: // format diskette track
BX_DEBUG_INT13_FL("floppy f05\n");
@@ -7462,7 +7778,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
SET_AH(1);
set_diskette_ret_status(1);
SET_CF(); // error occurred
- }
+ }
// see if drive exists
if (floppy_drive_exists(drive) == 0) {
@@ -7470,7 +7786,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
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) {
@@ -7480,8 +7796,8 @@ BX_DEBUG_INT13_FL("floppy f05\n");
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
}
+ }
// set up DMA controller for transfer
page = (ES >> 12); // upper 4 bits
@@ -7491,7 +7807,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
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
@@ -7502,7 +7818,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
+ }
outb(0x000a, 0x06);
outb(0x000c, 0x00); // clear flip-flop
@@ -7519,27 +7835,9 @@ BX_DEBUG_INT13_FL("floppy f05\n");
outb(0x000a, 0x02);
// set up floppy controller for transfer
- val8 = read_byte(0x0000, 0x043e);
- val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
- // turn on motor of selected drive, DMA & int enabled, normal operation
- if (drive)
- dor = 0x20;
- else
- dor = 0x10;
- dor |= 0x0c;
- dor |= drive;
- outb(0x03f2, dor);
+ floppy_prepare_controller(drive);
- // reset the disk motor timeout value of INT 08
- write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
-
- // check port 3f4 for drive readiness
- val8 = inb(0x3f4);
- if ( (val8 & 0xf0) != 0x80 )
- BX_PANIC("int13_diskette:f05: ctrl not ready\n");
-
- // send read-normal-data command (6 bytes) to controller
+ // 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
@@ -7550,20 +7848,29 @@ BX_DEBUG_INT13_FL("floppy f05\n");
ASM_START
sti
ASM_END
+
// wait on 40:3e bit 7 to become 1
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
- while ( val8 == 0 ) {
- val8 = (read_byte(0x0000, 0x043e) & 0x80);
+ 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 = 0; // separate asm from while() loop
- // turn off interrupts
+ 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(0x0000, 0x043e);
+ val8 = read_byte(0x0040, 0x003e);
val8 &= 0x7f;
- write_byte(0x0000, 0x043e, val8);
+ write_byte(0x0040, 0x003e, val8);
// check port 3f4 for accessibility to status bytes
val8 = inb(0x3f4);
if ( (val8 & 0xc0) != 0xc0 )
@@ -7915,8 +8222,9 @@ Bit16u seq_nr;
Bit16u bootseg;
Bit16u bootip;
Bit16u status;
+ Bit16u bootfirst;
- struct ipl_entry e;
+ ipl_entry_t e;
// if BX_ELTORITO_BOOT is not defined, old behavior
// check bit 5 in CMOS reg 0x2d. load either 0x00 or 0x80 into DL
@@ -7930,7 +8238,7 @@ Bit16u seq_nr;
// CMOS reg 0x38 & 0xf0 : 3rd boot device
// boot device codes:
// 0x00 : not defined
- // 0x01 : first floppy
+ // 0x01 : first floppy
// 0x02 : first harddrive
// 0x03 : first cdrom
// 0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot)
@@ -7942,16 +8250,25 @@ Bit16u seq_nr;
bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
bootdev >>= 4 * seq_nr;
bootdev &= 0xf;
- if (bootdev == 0) BX_PANIC("No bootable device.\n");
-
+
+ /* Read user selected device */
+ bootfirst = read_word(ebda_seg, IPL_BOOTFIRST_OFFSET);
+ if (bootfirst != 0xFFFF) {
+ bootdev = bootfirst;
+ /* User selected device not set */
+ write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF);
+ /* Reset boot sequence */
+ write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xFFFF);
+ } else if (bootdev == 0) BX_PANIC("No bootable device.\n");
+
/* Translate from CMOS runes to an IPL table offset by subtracting 1 */
bootdev -= 1;
-#else
+#else
if (seq_nr ==2) BX_PANIC("No more boot devices.");
- if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1))
+ if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1))
/* Boot from floppy if the bit is set or it's the second boot */
bootdev = 0x00;
- else
+ else
bootdev = 0x01;
#endif
@@ -7963,13 +8280,13 @@ Bit16u seq_nr;
/* Do the loading, and set up vector as a far pointer to the boot
* address, and bootdrv as the boot drive */
- print_boot_device(e.type);
+ print_boot_device(&e);
switch(e.type) {
- case 0x01: /* FDD */
- case 0x02: /* HDD */
+ case IPL_TYPE_FLOPPY: /* FDD */
+ case IPL_TYPE_HARDDISK: /* HDD */
- bootdrv = (e.type == 0x02) ? 0x80 : 0x00;
+ bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
bootseg = 0x07c0;
status = 0;
@@ -7984,7 +8301,7 @@ ASM_START
mov dl, _int18_function.bootdrv + 2[bp]
mov ax, _int18_function.bootseg + 2[bp]
mov es, ax ;; segment
- mov bx, #0x0000 ;; offset
+ xor bx, bx ;; offset
mov ah, #0x02 ;; function 2, read diskette sector
mov al, #0x01 ;; read 1 sector
mov ch, #0x00 ;; track 0
@@ -8002,7 +8319,7 @@ int19_load_done:
pop ax
pop bp
ASM_END
-
+
if (status != 0) {
print_boot_failure(e.type, 1);
return;
@@ -8010,7 +8327,7 @@ ASM_END
/* Always check the signature on a HDD boot sector; on FDD, only do
* the check if the CMOS doesn't tell us to skip it */
- if (e.type != 0x00 || !((inb_cmos(0x38) & 0x01))) {
+ if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) {
if (read_word(bootseg,0x1fe) != 0xaa55) {
print_boot_failure(e.type, 0);
return;
@@ -8028,7 +8345,7 @@ ASM_END
break;
#if BX_ELTORITO_BOOT
- case 0x03: /* CD-ROM */
+ case IPL_TYPE_CDROM: /* CD-ROM */
status = cdrom_boot();
// If failure
@@ -8047,7 +8364,7 @@ ASM_END
break;
#endif
- case 0x80: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */
+ case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */
bootseg = e.vector >> 16;
bootip = e.vector & 0xffff;
break;
@@ -8055,16 +8372,20 @@ ASM_END
default: return;
}
-
+ /* Debugging info */
+ BX_INFO("Booting from %x:%x\n", bootseg, bootip);
+
/* Jump to the boot vector */
ASM_START
mov bp, sp
+// push cs
+// push #int18_handler
;; Build an iret stack frame that will take us to the boot vector.
;; iret pops ip, then cs, then flags, so push them in the opposite order.
pushf
- mov ax, _int18_function.bootseg + 0[bp]
+ mov ax, _int18_function.bootseg + 0[bp]
push ax
- mov ax, _int18_function.bootip + 0[bp]
+ mov ax, _int18_function.bootip + 0[bp]
push ax
;; Set the magic number in ax and the boot drive in dl.
mov ax, #0xaa55
@@ -8267,7 +8588,11 @@ int1a_function(regs, ds, iret_addr)
} 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\n", regs.u.r16.dx, regs.u.r16.cx);
+ if (regs.u.r8.al == 0x02) {
+ BX_INFO("PCI device %04x:%04x not found at index %d\n", regs.u.r16.dx, regs.u.r16.cx, regs.u.r16.si);
+ } else {
+ BX_INFO("no PCI device with class code 0x%02x%04x found at index %d\n", regs.u.r8.cl, regs.u.r16.dx, regs.u.r16.si);
+ }
}
regs.u.r8.ah = regs.u.r8.bl;
SetCF(iret_addr.flags);
@@ -8313,11 +8638,11 @@ ASM_END
// Done waiting.
Bit16u segment, offset;
- offset = read_word( 0x40, 0x98 );
- segment = read_word( 0x40, 0x9A );
+ 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, 0x80 ); // Write to specified flag byte.
+ write_byte(segment, offset, read_byte(segment, offset) | 0x80 ); // Write to specified flag byte.
} else {
// Continue waiting.
time -= 0x3D1;
@@ -8525,13 +8850,18 @@ int13_notcdrom:
#endif
int13_disk:
+ ;; int13_harddisk modifies high word of EAX
+ shr eax, #16
+ push ax
call _int13_harddisk
+ pop ax
+ shl eax, #16
int13_out:
pop ds
pop es
popa
- iret
+ iret
;----------
;- INT18h -
@@ -8544,19 +8874,19 @@ int18_handler: ;; Boot Failure recovery: try the next device.
xor ax, ax
mov ss, ax
- ;; Get the boot sequence number out of the IPL memory
;; The first time we do this it will have been set to -1 so
;; we will start from device 0.
mov ds, ax
- mov bx, word ptr [EBDA_SEG_PTR]
+ mov bx, word ptr [0x40E] ;; EBDA segment
mov ds, bx ;; Set segment
mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number
inc bx ;; ++
mov IPL_SEQUENCE_OFFSET, bx ;; Write it back
- mov ds, ax ;; and reset the segment to zero.
+ mov ds, ax ;; and reset the segment to zero.
;; Call the C code for the next boot device
push bx
+
call _int18_function
;; Boot failed: invoke the boot recovery function...
@@ -8566,6 +8896,7 @@ int18_handler: ;; Boot Failure recovery: try the next device.
;- INT19h -
;----------
int19_relocated: ;; Boot function, relocated
+
;;
;; *** Warning: INT 19h resets the whole machine ***
;;
@@ -8577,10 +8908,12 @@ int19_relocated: ;; Boot function, relocated
;; boot sequence will start, which is more or less the required behaviour.
;;
;; Reset SP and SS
+
mov ax, #0xfffe
mov sp, ax
xor ax, ax
mov ss, ax
+
call _machine_reset
;----------
@@ -8594,7 +8927,7 @@ int1c_handler: ;; User Timer Tick
;- POST: Floppy Drive -
;----------------------
floppy_drive_post:
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
mov al, #0x00
@@ -8676,7 +9009,7 @@ hard_drive_post:
mov dx, #0x03f6
out dx, al
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
mov 0x0474, al /* hard disk status of last operation */
mov 0x0477, al /* hard disk port offset (XT only ???) */
@@ -8691,8 +9024,8 @@ hard_drive_post:
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, word ptr [EBDA_SEG_PTR], #0x003D)
- SET_INT_VECTOR(0x46, word ptr [EBDA_SEG_PTR], #0x004D)
+ SET_INT_VECTOR(0x41, word ptr [0x40E], #0x003D) /* EBDA:003D */
+ SET_INT_VECTOR(0x46, word ptr [0x40E], #0x004D) /* EBDA:004D */
;; move disk geometry data from CMOS to EBDA disk parameter table(s)
mov al, #0x12
@@ -8723,7 +9056,7 @@ post_d0_type47:
xor ax, ax
mov ds, ax
- mov ax, word ptr [EBDA_SEG_PTR]
+ mov ax, word ptr [0x40E] ;; EBDA segment
mov ds, ax
;;; Filling EBDA table for hard disk 0.
@@ -8869,7 +9202,9 @@ post_d1_type47:
;; 0x2b landing zone high D
;; 0x2c sectors/track E
;;; Fill EBDA table for hard disk 1.
- mov ax, #EBDA_SEG
+ xor ax, ax
+ mov ds, ax
+ mov ax, word ptr [0x40E] ;; EBDA segment
mov ds, ax
mov al, #0x28
out #0x70, al
@@ -8992,7 +9327,7 @@ ebda_post:
#endif
xor ax, ax ; mov EBDA seg into 40E
mov ds, ax
- mov word ptr [EBDA_SEG_PTR], #EBDA_SEG
+ mov word ptr [0x40E], #EBDA_SEG
ret;;
;--------------------
@@ -9000,13 +9335,42 @@ ebda_post:
;--------------------
; relocated here because the primary POST area isnt big enough.
eoi_jmp_post:
- call eoi_both_pics
+ mov al, #0x20
+ out #0xA0, al ;; slave PIC EOI
+ mov al, #0x20
+ out #0x20, al ;; master PIC EOI
+jmp_post_0x467:
xor ax, ax
mov ds, ax
jmp far ptr [0x467]
+iret_post_0x467:
+ xor ax, ax
+ mov ds, ax
+
+ mov sp, [0x467]
+ mov ss, [0x469]
+ iret
+
+retf_post_0x467:
+ xor ax, ax
+ mov ds, ax
+
+ mov sp, [0x467]
+ mov ss, [0x469]
+ retf
+
+s3_post:
+#if BX_ROMBIOS32
+ call rombios32_init
+#endif
+ call _s3_resume
+ mov bl, #0x00
+ and ax, ax
+ jz normal_post
+ call _s3_resume_panic
;--------------------
eoi_both_pics:
@@ -9159,16 +9523,22 @@ bios32_structure:
.align 16
bios32_entry_point:
- pushf
- cmp eax, #0x49435024
+ pushfd
+ cmp eax, #0x49435024 ;; "$PCI"
jne unknown_service
mov eax, #0x80000000
mov dx, #0x0cf8
out dx, eax
mov dx, #0x0cfc
in eax, dx
- cmp eax, #0x12378086
+#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
@@ -9177,12 +9547,15 @@ bios32_entry_point:
unknown_service:
mov al, #0x80
bios32_end:
- popf
+#ifdef BX_QEMU
+ and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
+#endif
+ popfd
retf
.align 16
pcibios_protected:
- pushf
+ pushfd
cli
push esi
push edi
@@ -9190,15 +9563,15 @@ pcibios_protected:
jne pci_pro_f02
mov bx, #0x0210
mov cx, #0
- mov edx, #0x20494350
+ mov edx, #0x20494350 ;; "PCI "
mov al, #0x01
jmp pci_pro_ok
pci_pro_f02: ;; find pci device
cmp al, #0x02
- jne pci_pro_f08
+ jne pci_pro_f03
shl ecx, #16
mov cx, dx
- mov bx, #0x0000
+ xor bx, bx
mov di, #0x00
pci_pro_devloop:
call pci_pro_select_reg
@@ -9215,6 +9588,27 @@ pci_pro_nextdev:
jne pci_pro_devloop
mov ah, #0x86
jmp pci_pro_fail
+pci_pro_f03: ;; find class code
+ cmp al, #0x03
+ jne pci_pro_f08
+ xor bx, bx
+ mov di, #0x08
+pci_pro_devloop2:
+ call pci_pro_select_reg
+ mov dx, #0x0cfc
+ in eax, dx
+ shr eax, #8
+ cmp eax, ecx
+ jne pci_pro_nextdev2
+ cmp si, #0
+ je pci_pro_ok
+ dec si
+pci_pro_nextdev2:
+ inc bx
+ cmp bx, #0x0100
+ jne pci_pro_devloop2
+ mov ah, #0x86
+ jmp pci_pro_fail
pci_pro_f08: ;; read configuration byte
cmp al, #0x08
jne pci_pro_f09
@@ -9288,16 +9682,20 @@ pci_pro_unknown:
pci_pro_fail:
pop edi
pop esi
- sti
- popf
+#ifdef BX_QEMU
+ and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
+#endif
+ popfd
stc
retf
pci_pro_ok:
xor ah, ah
pop edi
pop esi
- sti
- popf
+#ifdef BX_QEMU
+ and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
+#endif
+ popfd
clc
retf
@@ -9324,8 +9722,14 @@ pcibios_real:
out dx, eax
mov dx, #0x0cfc
in eax, dx
- cmp eax, #0x12378086
+#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
@@ -9339,7 +9743,7 @@ pci_present:
mov ax, #0x0001
mov bx, #0x0210
mov cx, #0
- mov edx, #0x20494350
+ mov edx, #0x20494350 ;; "PCI "
mov edi, #0xf0000
mov di, #pcibios_protected
clc
@@ -9348,10 +9752,10 @@ pci_real_f02: ;; find pci device
push esi
push edi
cmp al, #0x02
- jne pci_real_f08
+ jne pci_real_f03
shl ecx, #16
mov cx, dx
- mov bx, #0x0000
+ xor bx, bx
mov di, #0x00
pci_real_devloop:
call pci_real_select_reg
@@ -9368,7 +9772,30 @@ pci_real_nextdev:
jne pci_real_devloop
mov dx, cx
shr ecx, #16
- mov ah, #0x86
+ mov ax, #0x8602
+ jmp pci_real_fail
+pci_real_f03: ;; find class code
+ cmp al, #0x03
+ jne pci_real_f08
+ xor bx, bx
+ mov di, #0x08
+pci_real_devloop2:
+ call pci_real_select_reg
+ mov dx, #0x0cfc
+ in eax, dx
+ shr eax, #8
+ cmp eax, ecx
+ jne pci_real_nextdev2
+ cmp si, #0
+ je pci_real_ok
+ dec si
+pci_real_nextdev2:
+ inc bx
+ cmp bx, #0x0100
+ jne pci_real_devloop2
+ mov dx, cx
+ shr ecx, #16
+ mov ax, #0x8603
jmp pci_real_fail
pci_real_f08: ;; read configuration byte
cmp al, #0x08
@@ -9430,7 +9857,7 @@ pci_real_f0c: ;; write configuration word
jmp pci_real_ok
pci_real_f0d: ;; write configuration dword
cmp al, #0x0d
- jne pci_real_unknown
+ jne pci_real_f0e
call pci_real_select_reg
push dx
mov dx, #0x0cfc
@@ -9438,6 +9865,46 @@ pci_real_f0d: ;; write configuration dword
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:
@@ -9464,7 +9931,7 @@ pci_real_select_reg:
out dx, eax
pop dx
ret
-
+
.align 16
pci_routing_table_structure:
db 0x24, 0x50, 0x49, 0x52 ;; "$PIR" signature
@@ -9472,21 +9939,22 @@ pci_routing_table_structure:
dw 32 + (6 * 16) ;; table size
db 0 ;; PCI interrupt router bus
db 0x08 ;; PCI interrupt router DevFunc
- dw 0x0000 ;; PCI exclusive IRQs
+ dw 0x0000 ;; PCI exclusive IRQs
dw 0x8086 ;; compatible PCI interrupt router vendor ID
- dw 0x7000 ;; compatible PCI interrupt router device ID
+ dw 0x122e ;; compatible PCI interrupt router device ID
dw 0,0 ;; Miniport data
db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
- db 0x07 ;; checksum
+ db 0x37 ;; checksum
+pci_routing_table_structure_start:
;; first slot entry PCI-to-ISA (embedded)
db 0 ;; pci bus number
db 0x08 ;; pci device number (bit 7-3)
db 0x61 ;; link value INTA#: pointer into PCI2ISA config space
- dw 0x0c20 ;; IRQ bitmap INTA#
+ dw 0x0c20 ;; IRQ bitmap INTA#
db 0x62 ;; link value INTB#
- dw 0x0c20 ;; IRQ bitmap INTB#
+ dw 0x0c20 ;; IRQ bitmap INTB#
db 0x63 ;; link value INTC#
- dw 0x0c20 ;; IRQ bitmap INTC#
+ dw 0x0c20 ;; IRQ bitmap INTC#
db 0x60 ;; link value INTD#
dw 0x0c20 ;; IRQ bitmap INTD#
db 0 ;; physical slot (0 = embedded)
@@ -9495,11 +9963,11 @@ pci_routing_table_structure:
db 0 ;; pci bus number
db 0x10 ;; pci device number (bit 7-3)
db 0x62 ;; link value INTA#
- dw 0x0c20 ;; IRQ bitmap INTA#
+ dw 0x0c20 ;; IRQ bitmap INTA#
db 0x63 ;; link value INTB#
- dw 0x0c20 ;; IRQ bitmap INTB#
+ dw 0x0c20 ;; IRQ bitmap INTB#
db 0x60 ;; link value INTC#
- dw 0x0c20 ;; IRQ bitmap INTC#
+ dw 0x0c20 ;; IRQ bitmap INTC#
db 0x61 ;; link value INTD#
dw 0x0c20 ;; IRQ bitmap INTD#
db 1 ;; physical slot (0 = embedded)
@@ -9508,11 +9976,11 @@ pci_routing_table_structure:
db 0 ;; pci bus number
db 0x18 ;; pci device number (bit 7-3)
db 0x63 ;; link value INTA#
- dw 0x0c20 ;; IRQ bitmap INTA#
+ dw 0x0c20 ;; IRQ bitmap INTA#
db 0x60 ;; link value INTB#
- dw 0x0c20 ;; IRQ bitmap INTB#
+ dw 0x0c20 ;; IRQ bitmap INTB#
db 0x61 ;; link value INTC#
- dw 0x0c20 ;; IRQ bitmap INTC#
+ dw 0x0c20 ;; IRQ bitmap INTC#
db 0x62 ;; link value INTD#
dw 0x0c20 ;; IRQ bitmap INTD#
db 2 ;; physical slot (0 = embedded)
@@ -9521,11 +9989,11 @@ pci_routing_table_structure:
db 0 ;; pci bus number
db 0x20 ;; pci device number (bit 7-3)
db 0x60 ;; link value INTA#
- dw 0x0c20 ;; IRQ bitmap INTA#
+ dw 0x0c20 ;; IRQ bitmap INTA#
db 0x61 ;; link value INTB#
- dw 0x0c20 ;; IRQ bitmap INTB#
+ dw 0x0c20 ;; IRQ bitmap INTB#
db 0x62 ;; link value INTC#
- dw 0x0c20 ;; IRQ bitmap INTC#
+ dw 0x0c20 ;; IRQ bitmap INTC#
db 0x63 ;; link value INTD#
dw 0x0c20 ;; IRQ bitmap INTD#
db 3 ;; physical slot (0 = embedded)
@@ -9534,11 +10002,11 @@ pci_routing_table_structure:
db 0 ;; pci bus number
db 0x28 ;; pci device number (bit 7-3)
db 0x61 ;; link value INTA#
- dw 0x0c20 ;; IRQ bitmap INTA#
+ dw 0x0c20 ;; IRQ bitmap INTA#
db 0x62 ;; link value INTB#
- dw 0x0c20 ;; IRQ bitmap INTB#
+ dw 0x0c20 ;; IRQ bitmap INTB#
db 0x63 ;; link value INTC#
- dw 0x0c20 ;; IRQ bitmap INTC#
+ dw 0x0c20 ;; IRQ bitmap INTC#
db 0x60 ;; link value INTD#
dw 0x0c20 ;; IRQ bitmap INTD#
db 4 ;; physical slot (0 = embedded)
@@ -9547,17 +10015,352 @@ pci_routing_table_structure:
db 0 ;; pci bus number
db 0x30 ;; pci device number (bit 7-3)
db 0x62 ;; link value INTA#
- dw 0x0c20 ;; IRQ bitmap INTA#
+ dw 0x0c20 ;; IRQ bitmap INTA#
db 0x63 ;; link value INTB#
- dw 0x0c20 ;; IRQ bitmap INTB#
+ dw 0x0c20 ;; IRQ bitmap INTB#
db 0x60 ;; link value INTC#
- dw 0x0c20 ;; IRQ bitmap INTC#
+ dw 0x0c20 ;; IRQ bitmap INTC#
db 0x61 ;; link value INTD#
dw 0x0c20 ;; IRQ bitmap INTD#
db 5 ;; physical slot (0 = embedded)
db 0 ;; reserved
+pci_routing_table_structure_end:
+
+#if !BX_ROMBIOS32
+pci_irq_list:
+ db 11, 10, 9, 5;
+
+pcibios_init_sel_reg:
+ push eax
+ mov eax, #0x800000
+ mov ax, bx
+ shl eax, #8
+ and dl, #0xfc
+ or al, dl
+ mov dx, #0x0cf8
+ out dx, eax
+ pop eax
+ ret
+
+pcibios_init_iomem_bases:
+ push bp
+ mov bp, sp
+ mov eax, #0xe0000000 ;; base for memory init
+ push eax
+ mov ax, #0xc000 ;; base for i/o init
+ push ax
+ mov ax, #0x0010 ;; start at base address #0
+ push ax
+ mov bx, #0x0008
+pci_init_io_loop1:
+ mov dl, #0x00
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ in ax, dx
+ cmp ax, #0xffff
+ jz next_pci_dev
+ mov dl, #0x04 ;; disable i/o and memory space access
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ in al, dx
+ and al, #0xfc
+ out dx, al
+pci_init_io_loop2:
+ mov dl, [bp-8]
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ in eax, dx
+ test al, #0x01
+ jnz init_io_base
+ mov ecx, eax
+ mov eax, #0xffffffff
+ out dx, eax
+ in eax, dx
+ cmp eax, ecx
+ je next_pci_base
+ xor eax, #0xffffffff
+ mov ecx, eax
+ mov eax, [bp-4]
+ out dx, eax
+ add eax, ecx ;; calculate next free mem base
+ add eax, #0x01000000
+ and eax, #0xff000000
+ mov [bp-4], eax
+ jmp next_pci_base
+init_io_base:
+ mov cx, ax
+ mov ax, #0xffff
+ out dx, ax
+ in ax, dx
+ cmp ax, cx
+ je next_pci_base
+ xor ax, #0xfffe
+ mov cx, ax
+ mov ax, [bp-6]
+ out dx, ax
+ add ax, cx ;; calculate next free i/o base
+ add ax, #0x0100
+ and ax, #0xff00
+ mov [bp-6], ax
+next_pci_base:
+ mov al, [bp-8]
+ add al, #0x04
+ cmp al, #0x28
+ je enable_iomem_space
+ mov byte ptr[bp-8], al
+ jmp pci_init_io_loop2
+enable_iomem_space:
+ mov dl, #0x04 ;; enable i/o and memory space access if available
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ in al, dx
+ or al, #0x07
+ out dx, al
+next_pci_dev:
+ mov byte ptr[bp-8], #0x10
+ inc bx
+ cmp bx, #0x0100
+ jne pci_init_io_loop1
+ mov sp, bp
+ pop bp
+ ret
+
+pcibios_init_set_elcr:
+ push ax
+ push cx
+ mov dx, #0x04d0
+ test al, #0x08
+ jz is_master_pic
+ inc dx
+ and al, #0x07
+is_master_pic:
+ mov cl, al
+ mov bl, #0x01
+ shl bl, cl
+ in al, dx
+ or al, bl
+ out dx, al
+ pop cx
+ pop ax
+ ret
+
+pcibios_init_irqs:
+ push ds
+ push bp
+ mov ax, #0xf000
+ mov ds, ax
+ mov dx, #0x04d0 ;; reset ELCR1 + ELCR2
+ mov al, #0x00
+ out dx, al
+ inc dx
+ out dx, al
+ mov si, #pci_routing_table_structure
+ mov bh, [si+8]
+ mov bl, [si+9]
+ mov dl, #0x00
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ in 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
+ add dx, #2
+ out dx, ax
+ mov ax, [si+6]
+ sub ax, #0x20
+ shr ax, #4
+ mov cx, ax
+ add si, #0x20 ;; set pointer to 1st entry
+ mov bp, sp
+ mov ax, #pci_irq_list
+ push ax
+ xor ax, ax
+ push ax
+pci_init_irq_loop1:
+ mov bh, [si]
+ mov bl, [si+1]
+pci_init_irq_loop2:
+ mov dl, #0x00
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ in ax, dx
+ cmp ax, #0xffff
+ jnz pci_test_int_pin
+ test bl, #0x07
+ jz next_pir_entry
+ jmp next_pci_func
+pci_test_int_pin:
+ mov dl, #0x3c
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfd
+ in al, dx
+ and al, #0x07
+ jz next_pci_func
+ dec al ;; determine pirq reg
+ mov dl, #0x03
+ mul al, dl
+ add al, #0x02
+ xor ah, ah
+ mov bx, ax
+ mov al, [si+bx]
+ mov dl, al
+ mov bx, [bp]
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ and al, #0x03
+ add dl, al
+ in al, dx
+ cmp al, #0x80
+ jb pirq_found
+ mov bx, [bp-2] ;; pci irq list pointer
+ mov al, [bx]
+ out dx, al
+ inc bx
+ mov [bp-2], bx
+ call pcibios_init_set_elcr
+pirq_found:
+ mov bh, [si]
+ mov bl, [si+1]
+ add bl, [bp-3] ;; pci function number
+ mov dl, #0x3c
+ call pcibios_init_sel_reg
+ mov dx, #0x0cfc
+ out dx, al
+next_pci_func:
+ inc byte ptr[bp-3]
+ inc bl
+ test bl, #0x07
+ jnz pci_init_irq_loop2
+next_pir_entry:
+ add si, #0x10
+ mov byte ptr[bp-3], #0x00
+ loop pci_init_irq_loop1
+ mov sp, bp
+ pop bx
+pci_init_end:
+ pop bp
+ pop ds
+ ret
+#endif // !BX_ROMBIOS32
#endif // BX_PCIBIOS
+#if BX_ROMBIOS32
+rombios32_init:
+ ;; save a20 and enable it
+ in al, 0x92
+ push ax
+ or al, #0x02
+ out 0x92, al
+
+ ;; save SS:SP to the BDA
+ xor ax, ax
+ mov ds, ax
+ mov 0x0469, ss
+ mov 0x0467, sp
+
+ SEG CS
+ lidt [pmode_IDT_info]
+ SEG CS
+ lgdt [rombios32_gdt_48]
+ ;; set PE bit in CR0
+ mov eax, cr0
+ or al, #0x01
+ mov cr0, eax
+ ;; start protected mode code: ljmpl 0x10:rombios32_init1
+ db 0x66, 0xea
+ dw rombios32_05
+ dw 0x000f ;; high 16 bit address
+ dw 0x0010
+
+use32 386
+rombios32_05:
+ ;; init data segments
+ mov eax, #0x18
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ xor eax, eax
+ mov fs, ax
+ mov gs, ax
+ cld
+
+ ;; init the stack pointer to point below EBDA
+ mov ax, [0x040e]
+ shl eax, #4
+ mov esp, #-0x10
+ add esp, eax
+
+ ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32
+ push #0x04b0
+ push #0x04b2
+
+ ;; call rombios32 code
+ mov eax, #0x000e0000
+ call eax
+
+ ;; return to 16 bit protected mode first
+ db 0xea
+ dd rombios32_10
+ dw 0x20
+
+use16 386
+rombios32_10:
+ ;; restore data segment limits to 0xffff
+ mov ax, #0x28
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;; reset PE bit in CR0
+ mov eax, cr0
+ and al, #0xFE
+ mov cr0, eax
+
+ ;; far jump to flush CPU queue after transition to real mode
+ JMP_AP(0xf000, rombios32_real_mode)
+
+rombios32_real_mode:
+ ;; restore IDT to normal real-mode defaults
+ SEG CS
+ lidt [rmode_IDT_info]
+
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;; restore SS:SP from the BDA
+ mov ss, 0x0469
+ xor esp, esp
+ mov sp, 0x0467
+ ;; restore a20
+ pop ax
+ out 0x92, al
+ ret
+
+rombios32_gdt_48:
+ dw 0x30
+ dw rombios32_gdt
+ dw 0x000f
+
+rombios32_gdt:
+ dw 0, 0, 0, 0
+ dw 0, 0, 0, 0
+ dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10)
+ dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18)
+ dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff
+ dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff
+#endif // BX_ROMBIOS32
+
+
; parallel port detection: base address in DX, index in BX, timeout in CL
detect_parport:
push dx
@@ -9628,14 +10431,13 @@ checksum_loop:
ret
-;; We need a copy of this string, but we are not actually a PnP BIOS,
+;; We need a copy of this string, but we are not actually a PnP BIOS,
;; so make sure it is *not* aligned, so OSes will not see it if they scan.
.align 16
db 0
pnp_string:
.ascii "$PnP"
-
rom_scan:
;; Scan for existence of valid expansion ROMS.
;; Video ROM: from 0xC0000..0xC7FFF in 2k increments
@@ -9652,8 +10454,9 @@ rom_scan:
#if BX_TCGBIOS
call _tcpa_start_option_rom_scan /* specs: 3.2.3.3 + 10.4.3 */
#endif
- mov cx, #0xc000
+
rom_scan_loop:
+ push ax ;; Save AX
mov ds, cx
mov ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k
cmp [0], #0xAA55 ;; look for signature
@@ -9670,6 +10473,8 @@ rom_scan_loop:
add al, #0x04
block_count_rounded:
+ xor bx, bx ;; Restore DS back to 0000:
+ mov ds, bx
#if BX_TCGBIOS
push ax
push ds
@@ -9680,7 +10485,7 @@ block_count_rounded:
push ecx ;; segment where option rom is located at
call _tcpa_option_rom /* specs: 3.2.3.3 */
add sp, #4 ;; pop segment
- pop ecx ;; original ecx
+ pop ecx ;; original ecx
pop ds
pop ax
#endif
@@ -9704,11 +10509,11 @@ fetch_bdf:
xor ax, ax
mov al, [bx]
- ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
+ ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
;; That should stop it grabbing INT 19h; we will use its BEV instead.
mov bx, #0xf000
mov es, bx
- lea di, pnp_string
+ lea di, pnp_string
xor bx, bx ;; Restore DS back to 0000:
mov ds, bx
@@ -9721,8 +10526,8 @@ fetch_bdf:
add sp, #2 ;; Pop offset value
pop cx ;; Pop seg value (restore CX)
- ;; Look at the ROM's PnP Expansion header. Properly, we're supposed
- ;; to init all the ROMs and then go back and build an IPL table of
+ ;; Look at the ROM's PnP Expansion header. Properly, we're supposed
+ ;; to init all the ROMs and then go back and build an IPL table of
;; all the bootable devices, but we can get away with one pass.
mov ds, cx ;; ROM base
mov bx, 0x001a ;; 0x1A is the offset into ROM header that contains...
@@ -9730,7 +10535,7 @@ fetch_bdf:
cmp ax, #0x5024 ;; we look for signature "$PnP"
jne no_bev
mov ax, 2[bx]
- cmp ax, #0x506e
+ cmp ax, #0x506e
jne no_bev
mov ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector
@@ -9753,25 +10558,31 @@ fetch_bdf:
cli ;; In case expansion ROM BIOS turns IF on
add sp, #2 ;; Pop offset value
pop cx ;; Pop seg value (restore CX)
- jmp no_bev
+ jmp no_bev
no_bcv:
mov ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
cmp ax, #0x0000 ;; the Bootstrap Entry Vector, or zero if there is none.
je no_bev
- ;; Found a device that thinks it can boot the system. Record its BEV.
+ ;; Found a device that thinks it can boot the system. Record its BEV and product name string.
+ mov di, 0x10[bx] ;; Pointer to the product name string or zero if none
xor bx, bx
mov ds, bx
- mov bx, word ptr [EBDA_SEG_PTR]
- mov ds, bx ;; Go to the segment where the IPL table lives
+ mov bx, word ptr [0x40E] ;; EBDA segment
+ mov ds, bx ;; Go to the segment where the IPL table lives
mov bx, IPL_COUNT_OFFSET ;; Read the number of entries so far
cmp bx, #IPL_TABLE_ENTRIES
je no_bev ;; Get out if the table is full
shl bx, #0x4 ;; Turn count into offset (entries are 16 bytes)
- mov IPL_TABLE_OFFSET+0[bx], #0x80 ;; This entry is a BEV device
- mov IPL_TABLE_OFFSET+6[bx], cx ;; Build a far pointer from the segment...
- mov IPL_TABLE_OFFSET+4[bx], ax ;; and the offset
+ mov IPL_TABLE_OFFSET+0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device
+ mov IPL_TABLE_OFFSET+6[bx], cx ;; Build a far pointer from the segment...
+ mov IPL_TABLE_OFFSET+4[bx], ax ;; and the offset
+ cmp di, #0x0000
+ je no_prod_str
+ mov 0xA[bx], cx ;; Build a far pointer from the segment...
+ mov 8[bx], di ;; and the offset
+no_prod_str:
shr bx, #0x4 ;; Turn the offset back into a count
inc bx ;; We have one more entry now
mov IPL_COUNT_OFFSET, bx ;; Remember that.
@@ -9783,7 +10594,8 @@ 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
+ pop ax ;; Restore AX
+ cmp cx, ax
jbe rom_scan_loop
xor ax, ax ;; Restore DS back to 0000:
@@ -9848,10 +10660,36 @@ tcpa_post_part2:
#endif
-;; for 'C' strings and other data, insert them here with
-;; a the following hack:
-;; DATA_SEG_DEFS_HERE
+post_init_pic:
+ mov al, #0x11 ; send initialisation commands
+ out 0x20, al
+ out 0xa0, al
+ mov al, #0x08
+ out 0x21, al
+ mov al, #0x70
+ out 0xa1, al
+ mov al, #0x04
+ out 0x21, al
+ mov al, #0x02
+ out 0xa1, al
+ mov al, #0x01
+ out 0x21, al
+ out 0xa1, al
+ mov al, #0xb8
+ out 0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
+#if BX_USE_PS2_MOUSE
+ mov al, #0x8f
+#else
+ mov al, #0x9f
+#endif
+ out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
+ ret
+;; the following area can be used to write dynamically generated tables
+ .align 16
+bios_table_area_start:
+ dd 0xaafb4442
+ dd bios_table_area_end - bios_table_area_start - 8;
;--------
;- POST -
@@ -9887,17 +10725,66 @@ post:
;; Examine CMOS shutdown status.
mov al, bl
- mov dx, #EBDA_SEG
- mov ds, dx
- mov [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET], AL
+
+ ;; 0x00, 0x09, 0x0D+ = normal startup
+ cmp AL, #0x00
+ jz normal_post
+ cmp AL, #0x0d
+ jae normal_post
+ cmp AL, #0x09
+ je normal_post
+
+ ;; 0x05 = eoi + jmp via [0x40:0x67] jump
+ cmp al, #0x05
+ je eoi_jmp_post
+
+ ;; 0x0A = jmp via [0x40:0x67] jump
+ cmp al, #0x0a
+ je jmp_post_0x467
+
+ ;; 0x0B = iret via [0x40:0x67]
+ cmp al, #0x0b
+ je iret_post_0x467
+
+ ;; 0x0C = retf via [0x40:0x67]
+ cmp al, #0x0c
+ je retf_post_0x467
+
+ ;; Examine CMOS shutdown status.
+ ;; 0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status.
+ push bx
+ call _shutdown_status_panic
+
+#if 0
+ HALT(__LINE__)
+ ;
+ ;#if 0
+ ; 0xb0, 0x20, /* mov al, #0x20 */
+ ; 0xe6, 0x20, /* out 0x20, al ;send EOI to PIC */
+ ;#endif
+ ;
+ pop es
+ pop ds
+ popa
+ iret
+#endif
+
+normal_post:
+ ; case 0: normal startup
cli
mov ax, #0xfffe
mov sp, ax
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
mov ss, ax
+ ;; Save shutdown status
+ mov 0x04b0, bl
+
+ cmp bl, #0xfe
+ jz s3_post
+
;; zero out BIOS data area (40:00..40:ff)
mov es, ax
mov cx, #0x0080 ;; 128 words
@@ -9909,18 +10796,16 @@ post:
call _log_bios_start
;; set all interrupts to default handler
- mov bx, #0x0000 ;; offset index
+ xor bx, bx ;; offset index
mov cx, #0x0100 ;; counter (256 interrupts)
mov ax, #dummy_iret_handler
mov dx, #0xF000
post_default_ints:
mov [bx], ax
- inc bx
- inc bx
+ add bx, #2
mov [bx], dx
- inc bx
- inc bx
+ add bx, #2
loop post_default_ints
;; set vector 0x79 to zero
@@ -10076,67 +10961,41 @@ post_default_ints:
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
-
-#ifdef HVMASSIST
- call _enable_rom_write_access
- call _clobber_entry_point
- call _copy_e820_table
- call smbios_init
- call _disable_rom_write_access
-#endif
-
- call _init_boot_vectors
+ call post_init_pic
+ mov cx, #0xc000 ;; init vga bios
+ mov ax, #0xc780
call rom_scan
- call _print_bios_banner
+ call _print_bios_banner
+
+#if BX_ROMBIOS32
+ call rombios32_init
+#else
+#if BX_PCIBIOS
+ call pcibios_init_iomem_bases
+ call pcibios_init_irqs
+#endif //BX_PCIBIOS
+#endif
;;
;; Floppy setup
;;
call floppy_drive_post
-#if BX_USE_ATADRV
-
;;
;; Hard Drive setup
;;
call hard_drive_post
+#if BX_USE_ATADRV
+
;;
;; 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
@@ -10148,13 +11007,29 @@ post_default_ints:
;;
#endif // BX_ELTORITO_BOOT
- call _s3_resume
+#ifdef HVMASSIST
+ call _enable_rom_write_access
+ call _clobber_entry_point
+ call _copy_e820_table
+ call smbios_init
+ call _disable_rom_write_access
+#endif
+
+ call _init_boot_vectors
+
+ mov cx, #0xc800 ;; init option roms
+ mov ax, #0xe000
+ call rom_scan
+
+#if BX_ELTORITO_BOOT
call _interactive_bootkey
+#endif // BX_ELTORITO_BOOT
#if BX_TCGBIOS
call tcpa_post_part2
#endif
+ sti ;; enable interrupts
;; Start the boot sequence. See the comments in int19_relocated
;; for why we use INT 18h instead of INT 19h here.
int #0x18
@@ -10167,7 +11042,7 @@ nmi:
iret
int75_handler:
- out 0xf0, al // clear irq13
+ out 0xf0, al // clear irq13
call eoi_both_pics // clear interrupt
int 2 // legacy nmi call
iret
@@ -10266,7 +11141,7 @@ db 0x00
int14_handler:
push ds
pusha
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
call _int14_function
popa
@@ -10371,26 +11246,7 @@ int09_handler:
jz int09_finish
in al, #0x60 ;;read key from keyboard controller
- //test al, #0x80 ;;look for key release
- //jnz int09_process_key ;; dont pass releases to intercept?
-
- ;; check for extended key
- cmp al, #0xe0
- jne int09_call_int15_4f
-
- push ds
- xor ax, ax
- mov ds, ax
- mov al, BYTE [0x496] ;; mf2_state |= 0x01
- or al, #0x01
- mov BYTE [0x496], al
- pop ds
-
- in al, #0x60 ;;read another key from keyboard controller
-
sti
-
-int09_call_int15_4f:
push ds
pusha
#ifdef BX_CALL_INT15_4F
@@ -10400,8 +11256,27 @@ int09_call_int15_4f:
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_process_key:
+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
@@ -10419,8 +11294,6 @@ int09_finish:
iret
-
-
;----------------------------------------
;- INT 13h Diskette Service Entry Point -
;----------------------------------------
@@ -10459,7 +11332,7 @@ int0e_loop2:
je int0e_loop2
int0e_normal:
push ds
- mov ax, #0x0000 ;; segment 0000
+ xor ax, ax ;; segment 0000
mov ds, ax
call eoi_master_pic
mov al, 0x043e
@@ -10496,7 +11369,7 @@ db 0x08
int17_handler:
push ds
pusha
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
call _int17_function
popa
@@ -10686,11 +11559,11 @@ int1a_callfunction:
;;
int70_handler:
push ds
- pusha
+ pushad
xor ax, ax
mov ds, ax
call _int70_function
- popa
+ popad
pop ds
iret
@@ -10748,7 +11621,7 @@ int08_store_ticks:
.org 0xff00
-.ascii "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
+.ascii BIOS_COPYRIGHT_STRING
;------------------------------------------------
;- IRET Instruction for Dummy Interrupt Handler -
@@ -10770,7 +11643,7 @@ dummy_iret_handler:
#ifdef HVMTEST
jmp 0xd000:0x0003;
#else
- jmp 0xf000:post
+ jmp 0xf000:post
#endif
.org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
@@ -10783,10 +11656,10 @@ 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
+ * 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,
@@ -10962,328 +11835,10 @@ db 0,0,0,0,0,0,0,0 ; 24 bytes
db 0,0,0,0,0,0,0 ; 31 bytes
ASM_END
-#else // !HVMASSIST
-
+#endif // HVMASSIST
ASM_START
-.org 0xcc00
+.org 0xcff0
+bios_table_area_end:
// bcc-generated data will be placed here
-
-// For documentation of this config structure, look on developer.intel.com and
-// search for multiprocessor specification. Note that when you change anything
-// you must update the checksum (a pain!). It would be better to construct this
-// with C structures, or at least fill in the checksum automatically.
-//
-// Maybe this structs could be moved elsewhere than d000
-
-#if (BX_SMP_PROCESSORS==1)
- // no structure necessary.
-#elif (BX_SMP_PROCESSORS==2)
-// define the Intel MP Configuration Structure for 2 processors at
-// APIC ID 0,1. I/O APIC at ID=2.
-.align 16
-mp_config_table:
- db 0x50, 0x43, 0x4d, 0x50 ;; "PCMP" signature
- dw (mp_config_end-mp_config_table) ;; table length
- db 4 ;; spec rev
- db 0x65 ;; checksum
- .ascii "BOCHSCPU" ;; OEM id = "BOCHSCPU"
- db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1 "
- db 0x20, 0x20, 0x20, 0x20
- db 0x20, 0x20, 0x20, 0x20
- dw 0,0 ;; oem table ptr
- dw 0 ;; oem table size
- dw 20 ;; entry count
- dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
- dw 0 ;; extended table length
- db 0 ;; extended table checksum
- db 0 ;; reserved
-mp_config_proc0:
- db 0 ;; entry type=processor
- db 0 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 3 ;; cpu flags: enabled, bootstrap processor
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc1:
- db 0 ;; entry type=processor
- db 1 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_isa_bus:
- db 1 ;; entry type=bus
- db 0 ;; bus ID
- db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20 ;; bus type="ISA "
-mp_config_ioapic:
- db 2 ;; entry type=I/O APIC
- db 2 ;; apic id=2. linux will set.
- db 0x11 ;; I/O APIC version number
- db 1 ;; flags=1=enabled
- dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
-mp_config_irqs:
- db 3 ;; entry type=I/O interrupt
- db 0 ;; interrupt type=vectored interrupt
- db 0,0 ;; flags po=0, el=0 (linux uses as default)
- db 0 ;; source bus ID is ISA
- db 0 ;; source bus IRQ
- db 2 ;; destination I/O APIC ID
- db 0 ;; destination I/O APIC interrrupt in
- ;; repeat pattern for interrupts 0-15
- db 3,0,0,0,0,1,2,1
- db 3,0,0,0,0,2,2,2
- db 3,0,0,0,0,3,2,3
- db 3,0,0,0,0,4,2,4
- db 3,0,0,0,0,5,2,5
- db 3,0,0,0,0,6,2,6
- db 3,0,0,0,0,7,2,7
- db 3,0,0,0,0,8,2,8
- db 3,0,0,0,0,9,2,9
- db 3,0,0,0,0,10,2,10
- db 3,0,0,0,0,11,2,11
- db 3,0,0,0,0,12,2,12
- db 3,0,0,0,0,13,2,13
- db 3,0,0,0,0,14,2,14
- db 3,0,0,0,0,15,2,15
-#elif (BX_SMP_PROCESSORS==4)
-// define the Intel MP Configuration Structure for 4 processors at
-// APIC ID 0,1,2,3. I/O APIC at ID=4.
-.align 16
-mp_config_table:
- db 0x50, 0x43, 0x4d, 0x50 ;; "PCMP" signature
- dw (mp_config_end-mp_config_table) ;; table length
- db 4 ;; spec rev
- db 0xdd ;; checksum
- .ascii "BOCHSCPU" ;; OEM id = "BOCHSCPU"
- db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1 "
- db 0x20, 0x20, 0x20, 0x20
- db 0x20, 0x20, 0x20, 0x20
- dw 0,0 ;; oem table ptr
- dw 0 ;; oem table size
- dw 22 ;; entry count
- dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
- dw 0 ;; extended table length
- db 0 ;; extended table checksum
- db 0 ;; reserved
-mp_config_proc0:
- db 0 ;; entry type=processor
- db 0 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 3 ;; cpu flags: enabled, bootstrap processor
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc1:
- db 0 ;; entry type=processor
- db 1 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc2:
- db 0 ;; entry type=processor
- db 2 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc3:
- db 0 ;; entry type=processor
- db 3 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_isa_bus:
- db 1 ;; entry type=bus
- db 0 ;; bus ID
- db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20 ;; bus type="ISA "
-mp_config_ioapic:
- db 2 ;; entry type=I/O APIC
- db 4 ;; apic id=4. linux will set.
- db 0x11 ;; I/O APIC version number
- db 1 ;; flags=1=enabled
- dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
-mp_config_irqs:
- db 3 ;; entry type=I/O interrupt
- db 0 ;; interrupt type=vectored interrupt
- db 0,0 ;; flags po=0, el=0 (linux uses as default)
- db 0 ;; source bus ID is ISA
- db 0 ;; source bus IRQ
- db 4 ;; destination I/O APIC ID
- db 0 ;; destination I/O APIC interrrupt in
- ;; repeat pattern for interrupts 0-15
- db 3,0,0,0,0,1,4,1
- db 3,0,0,0,0,2,4,2
- db 3,0,0,0,0,3,4,3
- db 3,0,0,0,0,4,4,4
- db 3,0,0,0,0,5,4,5
- db 3,0,0,0,0,6,4,6
- db 3,0,0,0,0,7,4,7
- db 3,0,0,0,0,8,4,8
- db 3,0,0,0,0,9,4,9
- db 3,0,0,0,0,10,4,10
- db 3,0,0,0,0,11,4,11
- db 3,0,0,0,0,12,4,12
- db 3,0,0,0,0,13,4,13
- db 3,0,0,0,0,14,4,14
- db 3,0,0,0,0,15,4,15
-#elif (BX_SMP_PROCESSORS==8)
-// define the Intel MP Configuration Structure for 8 processors at
-// APIC ID 0,1,2,3,4,5,6,7. I/O APIC at ID=8.
-.align 16
-mp_config_table:
- db 0x50, 0x43, 0x4d, 0x50 ;; "PCMP" signature
- dw (mp_config_end-mp_config_table) ;; table length
- db 4 ;; spec rev
- db 0xc3 ;; checksum
- .ascii "BOCHSCPU" ;; OEM id = "BOCHSCPU"
- db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1 "
- db 0x20, 0x20, 0x20, 0x20
- db 0x20, 0x20, 0x20, 0x20
- dw 0,0 ;; oem table ptr
- dw 0 ;; oem table size
- dw 26 ;; entry count
- dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
- dw 0 ;; extended table length
- db 0 ;; extended table checksum
- db 0 ;; reserved
-mp_config_proc0:
- db 0 ;; entry type=processor
- db 0 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 3 ;; cpu flags: enabled, bootstrap processor
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc1:
- db 0 ;; entry type=processor
- db 1 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc2:
- db 0 ;; entry type=processor
- db 2 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc3:
- db 0 ;; entry type=processor
- db 3 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc4:
- db 0 ;; entry type=processor
- db 4 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc5:
- db 0 ;; entry type=processor
- db 5 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc6:
- db 0 ;; entry type=processor
- db 6 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_proc7:
- db 0 ;; entry type=processor
- db 7 ;; local APIC id
- db 0x11 ;; local APIC version number
- db 1 ;; cpu flags: enabled
- db 0,6,0,0 ;; cpu signature
- dw 0x201,0 ;; feature flags
- dw 0,0 ;; reserved
- dw 0,0 ;; reserved
-mp_config_isa_bus:
- db 1 ;; entry type=bus
- db 0 ;; bus ID
- db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20 ;; bus type="ISA "
-mp_config_ioapic:
- db 2 ;; entry type=I/O APIC
- db 8 ;; apic id=8
- db 0x11 ;; I/O APIC version number
- db 1 ;; flags=1=enabled
- dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
-mp_config_irqs:
- db 3 ;; entry type=I/O interrupt
- db 0 ;; interrupt type=vectored interrupt
- db 0,0 ;; flags po=0, el=0 (linux uses as default)
- db 0 ;; source bus ID is ISA
- db 0 ;; source bus IRQ
- db 8 ;; destination I/O APIC ID
- db 0 ;; destination I/O APIC interrrupt in
- ;; repeat pattern for interrupts 0-15
- db 3,0,0,0,0,1,8,1
- db 3,0,0,0,0,2,8,2
- db 3,0,0,0,0,3,8,3
- db 3,0,0,0,0,4,8,4
- db 3,0,0,0,0,5,8,5
- db 3,0,0,0,0,6,8,6
- db 3,0,0,0,0,7,8,7
- db 3,0,0,0,0,8,8,8
- db 3,0,0,0,0,9,8,9
- db 3,0,0,0,0,10,8,10
- db 3,0,0,0,0,11,8,11
- db 3,0,0,0,0,12,8,12
- db 3,0,0,0,0,13,8,13
- db 3,0,0,0,0,14,8,14
- db 3,0,0,0,0,15,8,15
-#else
-# error Sorry, rombios only has configurations for 1, 2, 4 or 8 processors.
-#endif // if (BX_SMP_PROCESSORS==...)
-
-mp_config_end: // this label used to find length of mp structure
- db 0
-
-#if (BX_SMP_PROCESSORS>1)
-.align 16
-mp_floating_pointer_structure:
-db 0x5f, 0x4d, 0x50, 0x5f ; "_MP_" signature
-dw mp_config_table, 0xf ;; pointer to MP configuration table
-db 1 ;; length of this struct in 16-bit byte chunks
-db 4 ;; MP spec revision
-db 0xc1 ;; checksum
-db 0 ;; MP feature byte 1. value 0 means look at the config table
-db 0,0,0,0 ;; MP feature bytes 2-5.
-#endif
-
ASM_END
-#endif // HVMASSIST
diff --git a/tools/firmware/rombios/rombios.h b/tools/firmware/rombios/rombios.h
new file mode 100644
index 0000000000..402172b21c
--- /dev/null
+++ b/tools/firmware/rombios/rombios.h
@@ -0,0 +1,70 @@
+/////////////////////////////////////////////////////////////////////////
+// $Id: rombios.h,v 1.8 2008/12/04 18:48:33 sshwarts Exp $
+/////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2006 Volker Ruppert
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+/* define it to include QEMU specific code */
+//#define BX_QEMU
+#define LEGACY
+
+#ifndef LEGACY
+# define BX_ROMBIOS32 1
+#else
+# define BX_ROMBIOS32 0
+#endif
+#define DEBUG_ROMBIOS 1
+
+#define PANIC_PORT 0x400
+#define PANIC_PORT2 0x401
+#define INFO_PORT 0x402
+#define DEBUG_PORT 0x403
+
+#define BIOS_PRINTF_HALT 1
+#define BIOS_PRINTF_SCREEN 2
+#define BIOS_PRINTF_INFO 4
+#define BIOS_PRINTF_DEBUG 8
+#define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
+#define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
+
+#define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
+
+// Defines the output macros.
+// BX_DEBUG goes to INFO port until we can easily choose debug info on a
+// per-device basis. Debug info are sent only in debug mode
+#if DEBUG_ROMBIOS
+# define BX_DEBUG(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
+#else
+# define BX_DEBUG(format, p...)
+#endif
+#define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
+#define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
+
+#define ACPI_DATA_SIZE 0x00010000L
+#define PM_IO_BASE 0xb000
+#define SMB_IO_BASE 0xb100
+
+ // Define the application NAME
+#if define HVMASSIST
+# define BX_APPNAME "HVMAssist"
+#elif defined(BX_QEMU)
+# define BX_APPNAME "QEMU"
+#elif defined(PLEX86)
+# define BX_APPNAME "Plex86"
+#else
+# define BX_APPNAME "Bochs"
+#endif