Hi, all
This patch update rombios to the latest Bochs's.
I'd like to corabolate bochs community to enhance the guest bios.
I'm not familiar around TCGBIOS.
So could you review the patch?
I tested boot/shutdown, S3 suspend/resume with linux guest.
Any comments are welcome :-)
Best Regards,
Akio Takebe
diff -r a76b4e00e186 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c Tue Dec 16 13:14:25 2008 +0000
+++ b/tools/firmware/rombios/rombios.c Wed Dec 17 23:38:15 2008 +0900
@@ -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
-
-// ROM BIOS for use with Bochs/Plex x86 emulation environment
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
+
+// 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@xxxxxxx)
// - 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 the application NAME
-#ifdef HVMASSIST
-# define BX_APPNAME "HVMAssist"
-#elif PLEX86
-# define BX_APPNAME "Plex86"
-#else
-# define BX_APPNAME "Bochs"
-#endif
+#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
+
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
cld
rep
movsb
-
+
memcpyb_end:
pop si
pop ds
@@ -378,14 +370,13 @@
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 @@
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 @@
cld
rep
movsd
-
+
memcpyd_end:
pop si
pop ds
@@ -426,16 +417,15 @@
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 @@
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 @@
ASM_START
push bp
mov bp, sp
-
+
push ax
push bx
push ds
@@ -481,50 +470,49 @@
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 @@
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 @@
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 @@
shr ebx, #16
lsr_exit:
ret
-
+
;; sl function
lsll:
lslul:
@@ -601,15 +589,15 @@
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 @@
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 @@
Bit8u revision;
Bit8u checksum;
} dpte_t;
-
+
typedef struct {
Bit8u iface; // ISA or PCI
Bit16u iobase1; // IO Base 1
@@ -685,15 +673,15 @@
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 @@
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 @@
Bit32u trsfbytes;
} ata_t;
-
-#if BX_ELTORITO_BOOT
- // ElTorito Device Emulation data
+
+#if BX_ELTORITO_BOOT
+ // ElTorito Device Emulation data
typedef struct {
Bit8u active;
Bit8u media;
@@ -730,20 +718,20 @@
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 @@
upcall_t upcall;
} ebda_data_t;
-
+
#define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1
#define EbdaData ((ebda_data_t *) 0)
@@ -779,7 +767,7 @@
Bit32u lba1;
Bit32u lba2;
} int13ext_t;
-
+
#define Int13Ext ((int13ext_t *) 0)
// Disk Physical Table definition
@@ -805,7 +793,7 @@
Bit8u reserved3;
Bit8u checksum;
} dpt_t;
-
+
#define Int13DPT ((dpt_t *) 0)
#endif // BX_USE_ATADRV
@@ -835,9 +823,9 @@
} 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;
@@ -870,6 +858,14 @@
Bit16u cs;
flags_t flags;
} iret_addr_t;
+
+typedef struct {
+ Bit16u type;
+ Bit16u flags;
+ Bit32u vector;
+ Bit32u description;
+ Bit32u reserved;
+ } ipl_entry_t;
@@ -910,8 +906,6 @@
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_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 @@
#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)
-
-#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)
+static char bios_cvs_version_string[] = "$Revision: 1.221 $ $Date: 2008/12/07
17:32:29 $";
+
+#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 @@
{ 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_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 @@
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 @@
pop bp
ASM_END
}
-
+
void
send(action, c)
Bit16u action;
@@ -1626,14 +1574,121 @@
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).
-//
-// Supports %[format_width][format]
-// where format can be d,x,c,s
+// A compact variable argument printf function.
+//
+// Supports %[format_width][length]format
+// where format can be x,X,u,d,s,S,c
+// and the optional length modifier is l (ell)
//--------------------------------------------------------------------------
void
bios_printf(action, s)
@@ -1644,7 +1699,7 @@
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,16 +1726,48 @@
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)
@@ -1689,7 +1776,13 @@
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 @@
}
if (action & BIOS_PRINTF_HALT) {
- // freeze in a busy loop.
+ // freeze in a busy loop.
ASM_START
cli
halt2_loop:
@@ -1740,8 +1833,8 @@
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,12 +1971,11 @@
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
//--------------------------------------------------------------------------
@@ -1939,6 +2031,11 @@
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 @@
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");
-#endif
- printf("\n");
-}
-
+ "TCG-enabled"
+#endif
+ "\n\n");
+}
//--------------------------------------------------------------------------
// BIOS Boot Specification 1.0.1 compatibility
//
-// Very basic support for the BIOS Boot Specification, which allows expansion
-// ROMs to register themselves as boot devices, instead of just stealing the
+// 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 void
-init_boot_vectors()
-{
- struct ipl_entry e;
+static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
+
+static void
+init_boot_vectors()
+{
+ ipl_entry_t e;
Bit16u count = 0;
Bit16u ss = get_SS();
+ 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 @@
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)
+print_boot_device(e)
+ ipl_entry_t *e;
+{
Bit16u type;
-{
- /* 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]);
+ 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_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");
- }
- printf("\n");
+ if (reason==0)
+ printf(": not a bootable disk");
+ else
+ printf(": could not read the boot disk");
+ }
+ printf("\n\n");
}
//--------------------------------------------------------------------------
@@ -2074,219 +2266,9 @@
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;
- }
-}
-
void
nmi_handler_msg()
@@ -2306,7 +2288,7 @@
#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 @@
outb(0xfedc, 0x00);
}
-void
+int
s3_resume()
{
Bit32u s3_wakeup_vector;
- Bit16u s3_wakeup_ip, s3_wakeup_cs;
- Bit8u cmos_shutdown_status;
-
-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
-
- if (cmos_shutdown_status != CMOS_SHUTDOWN_S3)
- return;
-
+ Bit8u s3_resume_flag;
+
+ s3_resume_flag = read_byte(0x40, 0xb0);
+#ifdef HVMASSIST
s3_wakeup_vector = get_s3_waking_vector();
- if (!s3_wakeup_vector)
- return;
-
- s3_wakeup_ip = s3_wakeup_vector & 0xF;
- s3_wakeup_cs = s3_wakeup_vector >> 4;
-
-ASM_START
- push .s3_resume.s3_wakeup_cs[bp]
- push .s3_resume.s3_wakeup_ip[bp]
- retf
-ASM_END
+#else
+ s3_wakeup_vector = read_dword(0x40, 0xb2);
+#endif
+
+ 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;
+
+ write_byte(0x40, 0xb0, 0);
+
+ /* setup wakeup vector */
+ write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */
+ write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */
+
+ BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4),
+ (s3_wakeup_vector & 0xF));
+ASM_START
+ jmpf [0x04b6]
+ASM_END
+ return 1;
}
#if BX_USE_ATADRV
@@ -2425,6 +2401,7 @@
// 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 @@
#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 @@
#define ATA_DATA_NO 0x00
#define ATA_DATA_IN 0x01
#define ATA_DATA_OUT 0x02
-
+
// ---------------------------------------------------------------------------
// ATA/ATAPI driver : initialization
// ---------------------------------------------------------------------------
@@ -2527,7 +2505,7 @@
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 @@
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 @@
write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0);
write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
-
- write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L);
- }
-
- // hdidmap and cdidmap init.
+
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
+ }
+
+ // hdidmap and cdidmap init.
for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
@@ -2562,6 +2541,58 @@
write_byte(ebda_seg,&EbdaData->ata.hdcount,0);
write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
+}
+
+#define TIMEOUT 0
+#define BSY 1
+#define NOT_BSY 2
+#define NOT_BSY_DRQ 3
+#define NOT_BSY_NOT_DRQ 4
+#define NOT_BSY_RDY 5
+
+#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
+
+int await_ide();
+static int await_ide(when_done,base,timeout)
+ Bit8u when_done;
+ Bit16u base;
+ Bit16u timeout;
+{
+ Bit32u time=0,last=0;
+ Bit16u status;
+ Bit8u result;
+ status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw
one away
+ for(;;) {
+ status = inb(base+ATA_CB_STAT);
+ time++;
+ if (when_done == BSY)
+ result = status & ATA_CB_STAT_BSY;
+ else if (when_done == NOT_BSY)
+ result = !(status & ATA_CB_STAT_BSY);
+ else if (when_done == NOT_BSY_DRQ)
+ result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
+ else if (when_done == NOT_BSY_NOT_DRQ)
+ result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
+ else if (when_done == NOT_BSY_RDY)
+ result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
+ else if (when_done == TIMEOUT)
+ result = 0;
+
+ if (result) return 0;
+ if (time>>16 != last) // mod 2048 each 16 ms
+ {
+ last = time >>16;
+ BX_DEBUG_ATA("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY)
%d time= %ld timeout= %d\n",when_done,time>>11, timeout);
+ }
+ if (status & ATA_CB_STAT_ERR)
+ {
+ BX_DEBUG_ATA("await_ide: ERROR
(TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout=
%d\n",when_done,time>>11, timeout);
+ return -1;
+ }
+ if ((timeout == 0) || ((time>>11) > timeout)) break;
+ }
+ BX_INFO("IDE time out\n");
+ return -1;
}
// ---------------------------------------------------------------------------
@@ -2604,7 +2635,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount);
write_byte(0x40,0x75, hdcount);
-
+
printf("\n");
// FIXME : should use bios=cmos|auto|disable bits
// FIXME : should know about translation bits
- // FIXME : move hard_drive_post here
-
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : software reset
+ // FIXME : move hard_drive_post here
+
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : software reset
// ---------------------------------------------------------------------------
// ATA-3
// 8.2.1 Software reset - Device 0
@@ -2876,7 +2920,8 @@
{
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 @@
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 @@
sn = inb(iobase1+ATA_CB_SN);
if ( (sc==0x01) && (sn==0x01) ) {
+ if (type == ATA_TYPE_ATA) //ATA
+ await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
+ else //ATAPI
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
+ }
// 8.2.1 (h) -- wait for not BSY
- max=0xff;
- while(--max>0) {
- Bit8u status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_BSY) == 0) break;
- }
- }
- }
-
-// 8.2.1 (i) -- wait for DRDY
- max=0xfff;
- while(--max>0) {
- Bit8u status = inb(iobase1+ATA_CB_STAT);
- if ((status & ATA_CB_STAT_RDY) != 0) break;
+ await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
}
// Enable interrupts
@@ -2931,7 +2966,7 @@
}
// ---------------------------------------------------------------------------
-// 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 @@
// 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 @@
// 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;
- }
- sector = (Bit16u) (lba & 0x000000ffL);
- lba >>= 8;
- cylinder = (Bit16u) (lba & 0x0000ffffL);
- lba >>= 16;
- head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
- }
+ lba_low &= (1UL << 24) - 1;
+ }
+ sector = (Bit16u) (lba_low & 0x000000ffL);
+ cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+ head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+ }
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, count);
@@ -3005,10 +3038,8 @@
outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) |
(Bit8u) head );
outb(iobase1 + ATA_CB_CMD, command);
- while (1) {
- status = inb(iobase1 + ATA_CB_STAT);
- if ( !(status & ATA_CB_STAT_BSY) ) break;
- }
+ 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_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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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;
- }
- sector = (Bit16u) (lba & 0x000000ffL);
- lba >>= 8;
- cylinder = (Bit16u) (lba & 0x0000ffffL);
- lba >>= 16;
- head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
- }
+ lba_low &= (1UL << 24) - 1;
+ }
+ sector = (Bit16u) (lba_low & 0x000000ffL);
+ cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+ head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+ }
outb(iobase1 + ATA_CB_FR, 0x00);
outb(iobase1 + ATA_CB_SC, count);
@@ -3159,10 +3189,8 @@
outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) |
(Bit8u) head );
outb(iobase1 + ATA_CB_CMD, command);
- while (1) {
- status = inb(iobase1 + ATA_CB_STAT);
- if ( !(status & ATA_CB_STAT_BSY) ) break;
- }
+ 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_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 @@
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 @@
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 @@
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 @@
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 @@
// 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_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 @@
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 @@
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 @@
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 @@
}
// 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 @@
// 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[];
-
- memsetb(get_SS(),atacmd,0,12);
-
- // Test Unit Ready
- if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO,
get_SS(), buffer) != 0)
- return 0x000f;
-
- if (atapi_get_sense(device) !=0 ) {
- memsetb(get_SS(),atacmd,0,12);
-
- // try to send Test Unit Ready again
- if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO,
get_SS(), buffer) != 0)
- return 0x000f;
-
- return atapi_get_sense(device);
- }
+ Bit8u packet[12];
+ Bit8u buf[8];
+ Bit32u block_len;
+ Bit32u sectors;
+ Bit32u timeout; //measured in ms
+ Bit32u time;
+ Bit8u asc, ascq;
+ Bit8u in_progress;
+ Bit16u ebda_seg = read_word(0x0040,0x000E);
+ if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) !=
ATA_TYPE_ATAPI) {
+ printf("not implemented for non-ATAPI device\n");
+ return -1;
+ }
+
+ BX_DEBUG_ATA("ata_detect_medium: begin\n");
+ memsetb(get_SS(),packet, 0, sizeof packet);
+ packet[0] = 0x25; /* READ CAPACITY */
+
+ /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT
+ * is reported by the device. If the device reports "IN PROGRESS",
+ * 30 seconds is added. */
+ timeout = 5000;
+ time = 0;
+ in_progress = 0;
+ while (time < timeout) {
+ if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L,
ATA_DATA_IN, get_SS(), buf) == 0)
+ goto ok;
+
+ if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) {
+ if (asc == 0x3a) { /* MEDIUM NOT PRESENT */
+ BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n");
+ return -1;
+ }
+
+ if (asc == 0x04 && ascq == 0x01 && !in_progress) {
+ /* IN PROGRESS OF BECOMING READY */
+ printf("Waiting for device to detect medium... ");
+ /* Allow 30 seconds more */
+ timeout = 30000;
+ in_progress = 1;
+ }
+ }
+ time += 100;
+ }
+ BX_DEBUG_ATA("read capacity failed\n");
+ return -1;
+ok:
+
+ block_len = (Bit32u) buf[4] << 24
+ | (Bit32u) buf[5] << 16
+ | (Bit32u) buf[6] << 8
+ | (Bit32u) buf[7] << 0;
+ BX_DEBUG_ATA("block_len=%u\n", block_len);
+
+ if (block_len!= 2048 && block_len!= 512)
+ {
+ printf("Unsupported sector size %u\n", block_len);
+ return -1;
+ }
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].blksize, block_len);
+
+ sectors = (Bit32u) buf[0] << 24
+ | (Bit32u) buf[1] << 16
+ | (Bit32u) buf[2] << 8
+ | (Bit32u) buf[3] << 0;
+
+ BX_DEBUG_ATA("sectors=%u\n", sectors);
+ if (block_len == 2048)
+ sectors <<= 2; /* # of sectors in 512-byte "soft" sector */
+ if (sectors !=
read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low))
+ printf("%dMB medium detected\n", sectors>>(20-9));
+ write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);
return 0;
}
- Bit16u
+ Bit16u
atapi_is_cdrom(device)
Bit8u device;
{
@@ -3636,7 +3721,7 @@
//
// Returns ah: emulated drive, al: error code
//
- Bit16u
+ Bit16u
cdrom_boot()
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
@@ -3649,9 +3734,12 @@
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);
@@ -3672,7 +3760,7 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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,16 +4757,178 @@
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 @@
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 @@
kbd_code |= (inb(0x60) << 8);
}
} while (--count>0);
- }
+ }
}
BX=kbd_code;
break;
@@ -4725,7 +5024,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
- }
- write_byte(0x0040, 0x18, mf2_flags);
+ if ((mf2_state & 0x01) == 0) {
+ shift_flags |= 0x04;
+ write_byte(0x0040, 0x17, shift_flags);
+ if (mf2_state & 0x02) {
+ mf2_state |= 0x04;
+ write_byte(0x0040, 0x96, mf2_state);
+ } else {
+ mf2_flags |= 0x01;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ }
break;
case 0x9d: /* Ctrl release */
- shift_flags &= ~0x04;
- write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 0x01) {
- mf2_flags &= ~0x04;
- } else {
- mf2_flags &= ~0x01;
- }
- write_byte(0x0040, 0x18, mf2_flags);
+ if ((mf2_state & 0x01) == 0) {
+ shift_flags &= ~0x04;
+ write_byte(0x0040, 0x17, shift_flags);
+ if (mf2_state & 0x02) {
+ mf2_state &= ~0x04;
+ write_byte(0x0040, 0x96, mf2_state);
+ } else {
+ mf2_flags &= ~0x01;
+ write_byte(0x0040, 0x18, mf2_flags);
+ }
+ }
break;
case 0x38: /* Alt press */
shift_flags |= 0x08;
write_byte(0x0040, 0x17, shift_flags);
- if (mf2_state & 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 @@
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);
- return;
- }
+ 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
@@ -5069,9 +5369,6 @@
Bit8u 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;
@@ -5122,9 +5419,8 @@
mouse_flags_2 = read_byte(ebda_seg, 0x0027);
if ( (mouse_flags_2 & 0x80) != 0x80 ) {
- // BX_PANIC("int74_function:\n");
- return;
- }
+ return;
+ }
package_count = mouse_flags_2 & 0x07;
index = mouse_flags_1 & 0x07;
@@ -5152,10 +5448,10 @@
#if BX_USE_ATADRV
void
-int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit32u lba;
+int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
+{
+ Bit32u lba_low, lba_high;
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit16u cylinder, head, sector;
Bit16u segment, offset;
@@ -5176,12 +5472,12 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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,365 @@
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;
+
+ write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
+ write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
+ write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device %
2))<<4 );
+ write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
+ write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
+ write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
+ write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
+ write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
+ write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
+ write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
+ if (size >=0x42)
+ write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
+ else
+ write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10);
+
+ checksum=0;
+ for (i=0; i<15; i++) checksum+=read_byte(ebda_seg,
((Bit8u*)(&EbdaData->ata.dpte)) + i);
+ checksum = ~checksum;
+ write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
+ }
+
+ // EDD 3.x
+ if(size >= 0x42) {
+ Bit8u channel, iface, checksum, i;
+ Bit16u iobase1;
+
+ channel = device / 2;
+ iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
+ iobase1 = read_word(ebda_seg,
&EbdaData->ata.channels[channel].iobase1);
+
+ write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
+ write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
+ write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
+ write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
+ write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
+
+ if (iface==ATA_IFACE_ISA) {
+ write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
+ write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
+ write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
+ write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
+ }
+ else {
+ // FIXME PCI
+ }
+ write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
+ write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
+ write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
+ write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
+
+ if (iface==ATA_IFACE_ISA) {
+ write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
+ write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
+ }
+ else {
+ // FIXME PCI
+ }
+ write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
+ write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
+ write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
+
+ checksum=0;
+ for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
+ checksum = ~checksum;
+ write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x4e: // // IBM/MS set hardware configuration
+ // DMA, prefetch, PIO maximum not supported
+ switch (GET_AL()) {
+ case 0x01:
+ case 0x03:
+ case 0x04:
+ case 0x06:
+ goto int13_success;
+ break;
+ default :
+ goto int13_fail;
+ }
+ break;
+
+ case 0x09: /* initialize drive parameters */
+ case 0x0c: /* seek to specified cylinder */
+ case 0x0d: /* alternate disk reset */
+ case 0x11: /* recalibrate */
+ case 0x14: /* controller internal diagnostic */
+ BX_INFO("int13_harddisk: function %02xh unimplemented, returns
success\n", GET_AH());
+ goto int13_success;
+ break;
+
+ case 0x0a: /* read disk sectors with ECC */
+ case 0x0b: /* write disk sectors with ECC */
+ case 0x18: // set media type for format
+ case 0x50: // IBM/MS send packet command
+ default:
+ BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n",
GET_AH());
+ goto int13_fail;
+ break;
+ }
+
+int13_fail:
+ SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+int13_fail_noah:
+ SET_DISK_RET_STATUS(GET_AH());
+int13_fail_nostatus:
+ SET_CF(); // error occurred
+ return;
+
+int13_success:
+ SET_AH(0x00); // no error
+int13_success_noah:
+ SET_DISK_RET_STATUS(0x00);
+ CLEAR_CF(); // no error
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// Start of int13 for cdrom
+// ---------------------------------------------------------------------------
+
+ void
+int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
+{
+ Bit16u ebda_seg=read_word(0x0040,0x000E);
+ Bit8u device, status, locks;
+ Bit8u atacmd[12];
+ Bit32u lba;
+ Bit16u count, segment, offset, i, size;
+
+ BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n",
AX, BX, CX, DX, ES);
+
+ SET_DISK_RET_STATUS(0x00);
+
+ /* basic check : device should be 0xE0+ */
+ if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
+ BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(),
GET_ELDL());
+ goto int13_fail;
+ }
+
+ // Get the ata channel
+ device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
+
+ /* basic check : device has to be valid */
+ if (device >= BX_MAX_ATA_DEVICES) {
+ BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n",
GET_AH(), GET_ELDL());
+ goto int13_fail;
+ }
+
+ switch (GET_AH()) {
+
+ // all those functions return SUCCESS
+ case 0x00: /* disk controller reset */
+ case 0x09: /* initialize drive parameters */
+ case 0x0c: /* seek to specified cylinder */
+ case 0x0d: /* alternate disk reset */
+ case 0x10: /* check drive ready */
+ case 0x11: /* recalibrate */
+ case 0x14: /* controller internal diagnostic */
+ case 0x16: /* detect disk change */
+ goto int13_success;
+ break;
+
+ // all those functions return disk write-protected
+ case 0x03: /* write disk sectors */
+ case 0x05: /* format disk track */
+ case 0x43: // IBM/MS extended write
+ SET_AH(0x03);
+ goto int13_fail_noah;
+ break;
+
+ case 0x01: /* read disk status */
+ status = read_byte(0x0040, 0x0074);
+ SET_AH(status);
+ SET_DISK_RET_STATUS(0);
+
+ /* set CF if error status read */
+ if (status) goto int13_fail_nostatus;
+ else goto int13_success_noah;
+ break;
+
+ case 0x15: /* read disk drive size */
+ SET_AH(0x02);
+ goto int13_fail_noah;
+ break;
+
+ case 0x41: // IBM/MS installation check
+ BX=0xaa55; // install check
+ SET_AH(0x30); // EDD 2.1
+ CX=0x0007; // ext disk access, removable and edd
+ goto int13_success_noah;
+ break;
+
+ case 0x42: // IBM/MS extended read
+ case 0x44: // IBM/MS verify sectors
+ case 0x47: // IBM/MS extended seek
+
+ count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
+ segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
+ offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
+
+ // Can't use 64 bits lba
+ lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
+ if (lba != 0L) {
+ BX_PANIC("int13_cdrom: function %02x. Can't use 64bits
lba\n",GET_AH());
+ goto int13_fail;
+ }
+
+ // Get 32 bits lba
+ lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
+
+ // If verify or seek
+ if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
+ goto int13_success;
+
+ memsetb(get_SS(),atacmd,0,12);
+ atacmd[0]=0x28; // READ command
+ atacmd[7]=(count & 0xff00) >> 8; // Sectors
+ atacmd[8]=(count & 0x00ff); // Sectors
+ atacmd[2]=(lba & 0xff000000) >> 24; // LBA
+ atacmd[3]=(lba & 0x00ff0000) >> 16;
+ atacmd[4]=(lba & 0x0000ff00) >> 8;
+ atacmd[5]=(lba & 0x000000ff);
+ status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L,
ATA_DATA_IN, segment,offset);
+
+ count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
+ write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
+
+ if (status != 0) {
+ BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
+ SET_AH(0x0c);
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x45: // IBM/MS lock/unlock drive
+ if (GET_AL() > 2) goto int13_fail;
+
+ locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
+
+ switch (GET_AL()) {
+ case 0 : // lock
+ if (locks == 0xff) {
+ SET_AH(0xb4);
+ SET_AL(1);
+ goto int13_fail_noah;
+ }
+ write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
+ SET_AL(1);
+ break;
+ case 1 : // unlock
+ if (locks == 0x00) {
+ SET_AH(0xb0);
+ SET_AL(0);
+ goto int13_fail_noah;
+ }
+ write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
+ SET_AL(locks==0?0:1);
+ break;
+ case 2 : // status
+ SET_AL(locks==0?0:1);
+ break;
+ }
+ goto int13_success;
+ break;
+
+ case 0x46: // IBM/MS eject media
+ locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
+
+ if (locks != 0) {
+ SET_AH(0xb1); // media locked
+ goto int13_fail_noah;
+ }
+ // FIXME should handle 0x31 no media in device
+ // FIXME should handle 0xb5 valid request failed
+
+ // Call removable media eject
+ ASM_START
+ push bp
+ mov bp, sp
+
+ mov ah, #0x52
+ int #0x15
+ mov _int13_cdrom.status + 2[bp], ah
+ jnc int13_cdrom_rme_end
+ mov _int13_cdrom.status, #1
+int13_cdrom_rme_end:
+ pop bp
+ ASM_END
+
+ if (status != 0) {
+ SET_AH(0xb1); // media locked
+ goto int13_fail_noah;
+ }
+
+ goto int13_success;
+ break;
+
+ case 0x48: // IBM/MS get drive parameters
+ size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
+
+ // Buffer is too small
+ if(size < 0x1a)
+ goto int13_fail;
+
+ // EDD 1.x
+ if(size >= 0x1a) {
+ Bit16u cylinders, heads, spt, blksize;
+
+ blksize = read_word(ebda_seg,
&EbdaData->ata.devices[device].blksize);
+
+ write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
+ write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media
change, lockable, max values
+ write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
+ write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); //
FIXME should be Bit64
+ write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
+ write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
+ }
+
+ // EDD 2.x
+ if(size >= 0x1e) {
+ Bit8u channel, dev, irq, mode, checksum, i;
+ Bit16u iobase1, iobase2, options;
+
+ write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
+
+ write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
+ write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
+
+ // Fill in dpte
+ channel = device / 2;
+ iobase1 = read_word(ebda_seg,
&EbdaData->ata.channels[channel].iobase1);
+ iobase2 = read_word(ebda_seg,
&EbdaData->ata.channels[channel].iobase2);
+ irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
+ mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
+
+ // FIXME atapi device
+ options = (1<<4); // lba translation
+ options |= (1<<5); // removable device
+ options |= (1<<6); // atapi device
options |= (mode==ATA_MODE_PIO32?1:0<<7);
- 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 );
@@ -5435,9 +6093,9 @@
write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
-
+
checksum=0;
- for (i=0; i<15; i++) checksum+=read_byte(ebda_seg,
(&EbdaData->ata.dpte) + i);
+ 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 +6121,7 @@
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 +6134,7 @@
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);
@@ -5491,6 +6149,12 @@
}
goto int13_success;
+ break;
+
+ case 0x49: // IBM/MS extended media change
+ // always send changed ??
+ SET_AH(06);
+ goto int13_fail_nostatus;
break;
case 0x4e: // // IBM/MS set hardware configuration
@@ -5507,361 +6171,6 @@
}
break;
- case 0x09: /* initialize drive parameters */
- case 0x0c: /* seek to specified cylinder */
- case 0x0d: /* alternate disk reset */
- case 0x11: /* recalibrate */
- case 0x14: /* controller internal diagnostic */
- BX_INFO("int13h_harddisk function %02xh unimplemented, returns
success\n", GET_AH());
- goto int13_success;
- break;
-
- case 0x0a: /* read disk sectors with ECC */
- case 0x0b: /* write disk sectors with ECC */
- case 0x18: // set media type for format
- case 0x50: // IBM/MS send packet command
- default:
- BX_INFO("int13_harddisk function %02xh unsupported, returns fail\n",
GET_AH());
- goto int13_fail;
- break;
- }
-
-int13_fail:
- SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
-int13_fail_noah:
- SET_DISK_RET_STATUS(GET_AH());
-int13_fail_nostatus:
- SET_CF(); // error occurred
- return;
-
-int13_success:
- SET_AH(0x00); // no error
-int13_success_noah:
- SET_DISK_RET_STATUS(0x00);
- CLEAR_CF(); // no error
- return;
-}
-
-// ---------------------------------------------------------------------------
-// Start of int13 for cdrom
-// ---------------------------------------------------------------------------
-
- void
-int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
- Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
- Bit16u ebda_seg=read_word(0x0040,0x000E);
- Bit8u device, status, locks;
- Bit8u atacmd[12];
- Bit32u lba;
- Bit16u count, segment, offset, i, size;
-
- BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n",
AX, BX, CX, DX, ES);
- // 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+ */
- if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
- BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(),
GET_ELDL());
- goto int13_fail;
- }
-
- // Get the ata channel
- device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
-
- /* basic check : device has to be valid */
- if (device >= BX_MAX_ATA_DEVICES) {
- BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n",
GET_AH(), GET_ELDL());
- goto int13_fail;
- }
-
- switch (GET_AH()) {
-
- // all those functions return SUCCESS
- case 0x00: /* disk controller reset */
- case 0x09: /* initialize drive parameters */
- case 0x0c: /* seek to specified cylinder */
- case 0x0d: /* alternate disk reset */
- case 0x10: /* check drive ready */
- case 0x11: /* recalibrate */
- case 0x14: /* controller internal diagnostic */
- case 0x16: /* detect disk change */
- goto int13_success;
- break;
-
- // all those functions return disk write-protected
- case 0x03: /* write disk sectors */
- case 0x05: /* format disk track */
- case 0x43: // IBM/MS extended write
- SET_AH(0x03);
- goto int13_fail_noah;
- break;
-
- case 0x01: /* read disk status */
- status = read_byte(0x0040, 0x0074);
- SET_AH(status);
- SET_DISK_RET_STATUS(0);
-
- /* set CF if error status read */
- if (status) goto int13_fail_nostatus;
- else goto int13_success_noah;
- break;
-
- case 0x15: /* read disk drive size */
- SET_AH(0x02);
- goto int13_fail_noah;
- break;
-
- case 0x41: // IBM/MS installation check
- BX=0xaa55; // install check
- SET_AH(0x30); // EDD 2.1
- CX=0x0007; // ext disk access, removable and edd
- goto int13_success_noah;
- break;
-
- case 0x42: // IBM/MS extended read
- case 0x44: // IBM/MS verify sectors
- case 0x47: // IBM/MS extended seek
-
- count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
- segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
- offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
-
- // Can't use 64 bits lba
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
- if (lba != 0L) {
- BX_PANIC("int13_cdrom: function %02x. Can't use 64bits
lba\n",GET_AH());
- goto int13_fail;
- }
-
- // Get 32 bits lba
- lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
-
- // If verify or seek
- if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
- goto int13_success;
-
- memsetb(get_SS(),atacmd,0,12);
- atacmd[0]=0x28; // READ command
- atacmd[7]=(count & 0xff00) >> 8; // Sectors
- atacmd[8]=(count & 0x00ff); // Sectors
- atacmd[2]=(lba & 0xff000000) >> 24; // LBA
- atacmd[3]=(lba & 0x00ff0000) >> 16;
- atacmd[4]=(lba & 0x0000ff00) >> 8;
- atacmd[5]=(lba & 0x000000ff);
- status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L,
ATA_DATA_IN, segment,offset);
-
- count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
- write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
-
- if (status != 0) {
- BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
- SET_AH(0x0c);
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x45: // IBM/MS lock/unlock drive
- if (GET_AL() > 2) goto int13_fail;
-
- locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
-
- switch (GET_AL()) {
- case 0 : // lock
- if (locks == 0xff) {
- SET_AH(0xb4);
- SET_AL(1);
- goto int13_fail_noah;
- }
- write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
- SET_AL(1);
- break;
- case 1 : // unlock
- if (locks == 0x00) {
- SET_AH(0xb0);
- SET_AL(0);
- goto int13_fail_noah;
- }
- write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
- SET_AL(locks==0?0:1);
- break;
- case 2 : // status
- SET_AL(locks==0?0:1);
- break;
- }
- goto int13_success;
- break;
-
- case 0x46: // IBM/MS eject media
- locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
-
- if (locks != 0) {
- SET_AH(0xb1); // media locked
- goto int13_fail_noah;
- }
- // FIXME should handle 0x31 no media in device
- // FIXME should handle 0xb5 valid request failed
-
- // Call removable media eject
- ASM_START
- push bp
- mov bp, sp
-
- mov ah, #0x52
- int 15
- mov _int13_cdrom.status + 2[bp], ah
- jnc int13_cdrom_rme_end
- mov _int13_cdrom.status, #1
-int13_cdrom_rme_end:
- pop bp
- ASM_END
-
- if (status != 0) {
- SET_AH(0xb1); // media locked
- goto int13_fail_noah;
- }
-
- goto int13_success;
- break;
-
- case 0x48: // IBM/MS get drive parameters
- size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
-
- // Buffer is too small
- if(size < 0x1a)
- goto int13_fail;
-
- // EDD 1.x
- if(size >= 0x1a) {
- Bit16u cylinders, heads, spt, blksize;
-
- blksize = read_word(ebda_seg,
&EbdaData->ata.devices[device].blksize);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
- write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media
change, lockable, max values
- write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff);
- write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
- write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); //
FIXME should be Bit64
- write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
- write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
- }
-
- // EDD 2.x
- if(size >= 0x1e) {
- Bit8u channel, dev, irq, mode, checksum, i;
- Bit16u iobase1, iobase2, options;
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
- write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset,
&EbdaData->ata.dpte);
-
- // Fill in dpte
- channel = device / 2;
- iobase1 = read_word(ebda_seg,
&EbdaData->ata.channels[channel].iobase1);
- iobase2 = read_word(ebda_seg,
&EbdaData->ata.channels[channel].iobase2);
- irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
- mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
-
- // FIXME atapi device
- options = (1<<4); // lba translation
- options |= (1<<5); // removable device
- options |= (1<<6); // atapi device
- options |= (mode==ATA_MODE_PIO32?1:0<<7);
-
- write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
- write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
- write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device %
2))<<4 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
- write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
- write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
- write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
- write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
- write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
- write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
-
- checksum=0;
- for (i=0; i<15; i++) checksum+=read_byte(ebda_seg,
(&EbdaData->ata.dpte) + i);
- checksum = ~checksum;
- write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
- }
-
- // EDD 3.x
- if(size >= 0x42) {
- Bit8u channel, iface, checksum, i;
- Bit16u iobase1;
-
- channel = device / 2;
- iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
- iobase1 = read_word(ebda_seg,
&EbdaData->ata.channels[channel].iobase1);
-
- write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
- write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
- write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
- write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
- write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
-
- if (iface==ATA_IFACE_ISA) {
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
- }
- else {
- // FIXME PCI
- }
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
- write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
-
- if (iface==ATA_IFACE_ISA) {
- write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
- write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
- write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
- }
- else {
- // FIXME PCI
- }
- write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
- write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
- write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
- write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
-
- checksum=0;
- for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
- checksum = ~checksum;
- write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
- }
-
- goto int13_success;
- break;
-
- case 0x49: // IBM/MS extended media change
- // always send changed ??
- SET_AH(06);
- goto int13_fail_nostatus;
- break;
-
- case 0x4e: // // IBM/MS set hardware configuration
- // DMA, prefetch, PIO maximum not supported
- switch (GET_AL()) {
- case 0x01:
- case 0x03:
- case 0x04:
- case 0x06:
- goto int13_success;
- break;
- default :
- goto int13_fail;
- }
- break;
-
// all those functions return unimplemented
case 0x02: /* read sectors */
case 0x04: /* verify sectors */
@@ -5909,7 +6218,7 @@
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 @@
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 @@
goto int13_fail;
}
-
switch (GET_AH()) {
// all those functions return SUCCESS
@@ -6010,7 +6317,7 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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,10 +7108,71 @@
#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)
@@ -6912,7 +7280,7 @@
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_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);
- }
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
+ do {
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
ASM_START
cli
ASM_END
// set 40:3e bit 7 to 0, and calibrated bit
- val8 = read_byte(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 @@
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 @@
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 @@
set_diskette_ret_status(1);
SET_CF();
return;
- }
+ }
drive_type = inb_cmos(0x10);
if (drive == 0)
@@ -7074,7 +7418,7 @@
set_diskette_ret_status(0x80);
SET_CF();
return;
- }
+ }
SET_AH(0);
set_diskette_ret_status(0);
CLEAR_CF(); // successful
@@ -7087,7 +7431,7 @@
SET_AH(val8);
if (val8) {
SET_CF();
- }
+ }
return;
case 0x02: // Read Diskette Sectors
@@ -7099,15 +7443,15 @@
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 @@
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 @@
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
- }
+ }
+ }
if (ah == 0x02) {
// Read Diskette Sectors
@@ -7146,7 +7490,7 @@
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 @@
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 @@
//--------------------------------------
// 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 @@
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);
- }
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
+ do {
+ val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ floppy_reset_controller();
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors read
+ SET_CF(); // error occurred
+ return;
+ }
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
ASM_START
cli
ASM_END
// set 40:3e bit 7 to 0
- val8 = read_byte(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 @@
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 @@
SET_AH(0x00); // success
CLEAR_CF(); // success
return;
- }
- else if (ah == 0x03) {
+ } else if (ah == 0x03) {
// Write Diskette Sectors
//-----------------------------------
@@ -7301,7 +7631,7 @@
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 @@
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 @@
//--------------------------------------
// 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:f03: ctrl not ready\n");
-
- // send read-normal-data command (9 bytes) to controller
+ floppy_prepare_controller(drive);
+
+ // send write-normal-data command (9 bytes) to controller
outb(0x03f5, 0xc5); // c5: write normal data
outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
outb(0x03f5, track);
@@ -7372,27 +7681,35 @@
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);
- }
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
+ do {
+ val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ floppy_reset_controller();
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_AL(0); // no sectors written
+ SET_CF(); // error occurred
+ return;
+ }
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
ASM_START
cli
ASM_END
// set 40:3e bit 7 to 0
- val8 = read_byte(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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
SET_AL(0); // no sectors read
SET_CF(); // error occurred
return;
- }
+ }
outb(0x000a, 0x06);
outb(0x000c, 0x00); // clear flip-flop
@@ -7519,27 +7835,9 @@
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);
-
- // 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
+ floppy_prepare_controller(drive);
+
+ // send format-track command (6 bytes) to controller
outb(0x03f5, 0x4d); // 4d: format track
outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
outb(0x03f5, 2); // 512 byte sector size
@@ -7550,20 +7848,29 @@
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);
- }
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
+ do {
+ val8 = read_byte(0x0040, 0x0040);
+ if (val8 == 0) {
+ floppy_reset_controller();
+ SET_AH(0x80); // drive not ready (timeout)
+ set_diskette_ret_status(0x80);
+ SET_CF(); // error occurred
+ return;
+ }
+ val8 = (read_byte(0x0040, 0x003e) & 0x80);
+ } while ( val8 == 0 );
+
+ val8 = 0; // separate asm from while() loop
+ // turn off interrupts
ASM_START
cli
ASM_END
// set 40:3e bit 7 to 0
- val8 = read_byte(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 bootseg;
Bit16u bootip;
Bit16u status;
-
- struct ipl_entry e;
+ Bit16u bootfirst;
+
+ ipl_entry_t e;
// if BX_ELTORITO_BOOT is not defined, old behavior
// check bit 5 in CMOS reg 0x2d. load either 0x00 or 0x80 into DL
@@ -7930,7 +8238,7 @@
// 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 @@
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 @@
/* 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 */
-
- bootdrv = (e.type == 0x02) ? 0x80 : 0x00;
+ case IPL_TYPE_FLOPPY: /* FDD */
+ case IPL_TYPE_HARDDISK: /* HDD */
+
+ bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
bootseg = 0x07c0;
status = 0;
@@ -7984,7 +8301,7 @@
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 @@
pop ax
pop bp
ASM_END
-
+
if (status != 0) {
print_boot_failure(e.type, 1);
return;
@@ -8010,7 +8327,7 @@
/* 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 @@
break;
#if BX_ELTORITO_BOOT
- case 0x03: /* CD-ROM */
+ case IPL_TYPE_CDROM: /* CD-ROM */
status = cdrom_boot();
// If failure
@@ -8047,7 +8364,7 @@
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 @@
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 @@
} 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 @@
// 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 @@
#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 @@
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 @@
;- INT19h -
;----------
int19_relocated: ;; Boot function, relocated
+
;;
;; *** Warning: INT 19h resets the whole machine ***
;;
@@ -8577,10 +8908,12 @@
;; 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 @@
;- POST: Floppy Drive -
;----------------------
floppy_drive_post:
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
mov al, #0x00
@@ -8676,7 +9009,7 @@
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 @@
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 @@
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 @@
;; 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 @@
#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 @@
;--------------------
; 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 @@
.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 @@
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 @@
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
@@ -9213,6 +9586,27 @@
inc bx
cmp bx, #0x0100
jne pci_pro_devloop
+ mov ah, #0x86
+ jmp pci_pro_fail
+pci_pro_f03: ;; find class code
+ cmp al, #0x03
+ jne pci_pro_f08
+ xor bx, bx
+ mov di, #0x08
+pci_pro_devloop2:
+ call pci_pro_select_reg
+ mov dx, #0x0cfc
+ in eax, dx
+ shr eax, #8
+ cmp eax, ecx
+ jne pci_pro_nextdev2
+ cmp si, #0
+ je pci_pro_ok
+ dec si
+pci_pro_nextdev2:
+ inc bx
+ cmp bx, #0x0100
+ jne pci_pro_devloop2
mov ah, #0x86
jmp pci_pro_fail
pci_pro_f08: ;; read configuration byte
@@ -9288,16 +9682,20 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
out dx, eax
pop dx
ret
-
+
.align 16
pci_routing_table_structure:
db 0x24, 0x50, 0x49, 0x52 ;; "$PIR" signature
@@ -9472,21 +9939,22 @@
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 @@
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 @@
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 @@
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 @@
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,16 +10015,351 @@
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:
@@ -9628,13 +10431,12 @@
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.
@@ -9652,8 +10454,9 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
#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,16 +10725,65 @@
;; 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
@@ -9909,18 +10796,16 @@
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,28 +10961,51 @@
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
+ call post_init_pic
+
+ mov cx, #0xc000 ;; init vga bios
+ mov ax, #0xc780
+ call rom_scan
+
+ call _print_bios_banner
+
+#if BX_ROMBIOS32
+ call rombios32_init
+#else
+#if BX_PCIBIOS
+ call pcibios_init_iomem_bases
+ call pcibios_init_irqs
+#endif //BX_PCIBIOS
+#endif
+
+ ;;
+ ;; Floppy setup
+ ;;
+ call floppy_drive_post
+
+ ;;
+ ;; Hard Drive setup
+ ;;
+ call hard_drive_post
+
+#if BX_USE_ATADRV
+
+ ;;
+ ;; ATA/ATAPI driver setup
+ ;;
+ call _ata_init
+ call _ata_detect
+ ;;
+
+#endif // BX_USE_ATADRV
+
+#if BX_ELTORITO_BOOT
+ ;;
+ ;; eltorito floppy/harddisk emulation from cd
+ ;;
+ call _cdemu_init
+ ;;
+#endif // BX_ELTORITO_BOOT
#ifdef HVMASSIST
call _enable_rom_write_access
@@ -10109,52 +11017,19 @@
call _init_boot_vectors
+ mov cx, #0xc800 ;; init option roms
+ mov ax, #0xe000
call rom_scan
- call _print_bios_banner
-
- ;;
- ;; Floppy setup
- ;;
- call floppy_drive_post
-
-#if BX_USE_ATADRV
-
- ;;
- ;; Hard Drive setup
- ;;
- call hard_drive_post
-
- ;;
- ;; ATA/ATAPI driver setup
- ;;
- call _ata_init
- call _ata_detect
- ;;
-#else // BX_USE_ATADRV
-
- ;;
- ;; Hard Drive setup
- ;;
- call hard_drive_post
-
-#endif // BX_USE_ATADRV
-
-#if BX_ELTORITO_BOOT
- ;;
- ;; eltorito floppy/harddisk emulation from cd
- ;;
- call _cdemu_init
- ;;
+#if BX_ELTORITO_BOOT
+ call _interactive_bootkey
#endif // BX_ELTORITO_BOOT
-
- call _s3_resume
- call _interactive_bootkey
#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 @@
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 @@
int14_handler:
push ds
pusha
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
call _int14_function
popa
@@ -10371,26 +11246,7 @@
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 @@
jnc int09_done
#endif
-
-//int09_process_key:
+ ;; check for extended key
+ cmp al, #0xe0
+ jne int09_check_pause
+ xor ax, ax
+ mov ds, ax
+ mov al, BYTE [0x496] ;; mf2_state |= 0x02
+ or al, #0x02
+ mov BYTE [0x496], al
+ jmp int09_done
+
+int09_check_pause: ;; check for pause key
+ cmp al, #0xe1
+ jne int09_process_key
+ xor ax, ax
+ mov ds, ax
+ mov al, BYTE [0x496] ;; mf2_state |= 0x01
+ or al, #0x01
+ mov BYTE [0x496], al
+ jmp int09_done
+
+int09_process_key:
mov bx, #0xf000
mov ds, bx
call _int09_function
@@ -10417,8 +11292,6 @@
out #0x64, al
pop ax
iret
-
-
;----------------------------------------
@@ -10459,7 +11332,7 @@
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 @@
int17_handler:
push ds
pusha
- mov ax, #0x0000
+ xor ax, ax
mov ds, ax
call _int17_function
popa
@@ -10686,11 +11559,11 @@
;;
int70_handler:
push ds
- pusha
+ pushad
xor ax, ax
mov ds, ax
call _int70_function
- popa
+ popad
pop ds
iret
@@ -10748,7 +11621,7 @@
.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 @@
#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 @@
.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 ; 31 bytes
ASM_END
-#else // !HVMASSIST
-
-ASM_START
-.org 0xcc00
+#endif // HVMASSIST
+ASM_START
+.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
+ASM_END
+
diff -r a76b4e00e186 tools/firmware/rombios/rombios.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/rombios.h Wed Dec 17 23:38:15 2008 +0900
@@ -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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|