[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] rombios: Update to Bochs latest
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1229611973 0 # Node ID 0a393ba0ec0a6898d039bed9e0c7b4a809c25f07 # Parent 768759d4e319f8c46a8558782a9bf1c7982e662d rombios: Update to Bochs latest Signed-off-by: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx> --- tools/firmware/rombios/rombios.c | 3995 ++++++++++++++++++++++----------------- tools/firmware/rombios/rombios.h | 70 2 files changed, 2345 insertions(+), 1720 deletions(-) diff -r 768759d4e319 -r 0a393ba0ec0a tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Thu Dec 18 11:29:33 2008 +0000 +++ b/tools/firmware/rombios/rombios.c Thu Dec 18 14:52:53 2008 +0000 @@ -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 @@ use16 286 MACRO HALT ;; the HALT macro is called with the line number of the HALT call. - ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex + ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex ;; to print a BX_PANIC message. This will normally halt the simulation ;; with a message such as "BIOS panic at rombios.c, line 4091". ;; However, users can choose to make panics non-fatal and continue. @@ -296,9 +288,9 @@ typedef unsigned long Bit32u; void memsetb(seg,offset,value,count); void memcpyb(dseg,doffset,sseg,soffset,count); void memcpyd(dseg,doffset,sseg,soffset,count); - + // memset of count bytes - void + void memsetb(seg,offset,value,count) Bit16u seg; Bit16u offset; @@ -308,14 +300,14 @@ typedef unsigned long Bit32u; ASM_START push bp mov bp, sp - + push ax push cx push es push di - + mov cx, 10[bp] ; count - cmp cx, #0x00 + test cx, cx je memsetb_end mov ax, 4[bp] ; segment mov es, ax @@ -325,19 +317,19 @@ typedef unsigned long Bit32u; cld rep stosb - + memsetb_end: pop di pop es pop cx pop ax - + pop bp ASM_END } - + // memcpy of count bytes - void + void memcpyb(dseg,doffset,sseg,soffset,count) Bit16u dseg; Bit16u doffset; @@ -348,16 +340,16 @@ typedef unsigned long Bit32u; ASM_START push bp mov bp, sp - + push ax push cx push es push di push ds push si - + mov cx, 12[bp] ; count - cmp cx, #0x0000 + test cx, cx je memcpyb_end mov ax, 4[bp] ; dsegment mov es, ax @@ -370,7 +362,7 @@ typedef unsigned long Bit32u; cld rep movsb - + memcpyb_end: pop si pop ds @@ -378,14 +370,13 @@ typedef unsigned long Bit32u; pop es pop cx pop ax - + pop bp ASM_END } -#if 0 // memcpy of count dword - void + void memcpyd(dseg,doffset,sseg,soffset,count) Bit16u dseg; Bit16u doffset; @@ -396,16 +387,16 @@ typedef unsigned long Bit32u; ASM_START push bp mov bp, sp - + push ax push cx push es push di push ds push si - + mov cx, 12[bp] ; count - cmp cx, #0x0000 + test cx, cx je memcpyd_end mov ax, 4[bp] ; dsegment mov es, ax @@ -418,7 +409,7 @@ typedef unsigned long Bit32u; cld rep movsd - + memcpyd_end: pop si pop ds @@ -426,16 +417,15 @@ typedef unsigned long Bit32u; pop es pop cx pop ax - + pop bp ASM_END } -#endif // read_dword and write_dword functions static Bit32u read_dword(); static void write_dword(); - + Bit32u read_dword(seg, offset) Bit16u seg; @@ -444,25 +434,24 @@ typedef unsigned long Bit32u; ASM_START push bp mov bp, sp - + push bx push ds mov ax, 4[bp] ; segment mov ds, ax mov bx, 6[bp] ; offset mov ax, [bx] - inc bx - inc bx + add bx, #2 mov dx, [bx] ;; ax = return value (word) ;; dx = return value (word) pop ds pop bx - + pop bp ASM_END } - + void write_dword(seg, offset, data) Bit16u seg; @@ -472,7 +461,7 @@ typedef unsigned long Bit32u; ASM_START push bp mov bp, sp - + push ax push bx push ds @@ -481,50 +470,49 @@ typedef unsigned long Bit32u; mov bx, 6[bp] ; offset mov ax, 8[bp] ; data word mov [bx], ax ; write data word - inc bx - inc bx + add bx, #2 mov ax, 10[bp] ; data word mov [bx], ax ; write data word pop ds pop bx pop ax - + pop bp ASM_END } - + // Bit32u (unsigned long) and long helper functions ASM_START - + ;; and function landl: landul: - SEG SS + SEG SS and ax,[di] - SEG SS + SEG SS and bx,2[di] ret - + ;; add function laddl: laddul: - SEG SS + SEG SS add ax,[di] - SEG SS + SEG SS adc bx,2[di] ret - + ;; cmp function lcmpl: lcmpul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx shr ebx, #16 SEG SS cmp eax, dword ptr [di] ret - + ;; sub function lsubl: lsubul: @@ -533,26 +521,26 @@ typedef unsigned long Bit32u; SEG SS sbb bx,2[di] ret - + ;; mul function lmull: lmulul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx SEG SS mul eax, dword ptr [di] mov ebx, eax shr ebx, #16 ret - + ;; dec function ldecl: ldecul: SEG SS dec dword ptr [bx] ret - + ;; or function lorl: lorul: @@ -561,31 +549,31 @@ typedef unsigned long Bit32u; SEG SS or bx,2[di] ret - + ;; inc function lincl: lincul: SEG SS inc dword ptr [bx] ret - + ;; tst function ltstl: ltstul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx shr ebx, #16 test eax, eax ret - + ;; sr function lsrul: mov cx,di jcxz lsr_exit and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx lsr_loop: shr eax, #1 loop lsr_loop @@ -593,7 +581,7 @@ typedef unsigned long Bit32u; shr ebx, #16 lsr_exit: ret - + ;; sl function lsll: lslul: @@ -601,15 +589,15 @@ typedef unsigned long Bit32u; jcxz lsl_exit and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx - lsl_loop: + or eax, ebx + lsl_loop: shl eax, #1 loop lsl_loop mov ebx, eax shr ebx, #16 lsl_exit: ret - + idiv_: cwd idiv bx @@ -623,7 +611,7 @@ typedef unsigned long Bit32u; ldivul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx xor edx, edx SEG SS mov bx, 2[di] @@ -672,7 +660,7 @@ typedef struct { Bit8u revision; Bit8u checksum; } dpte_t; - + typedef struct { Bit8u iface; // ISA or PCI Bit16u iobase1; // IO Base 1 @@ -685,15 +673,15 @@ typedef struct { Bit8u device; // Detected type of attached devices (hd/cd/none) Bit8u removable; // Removable device flag Bit8u lock; // Locks for removable devices - // Bit8u lba_capable; // LBA capable flag - always yes for bochs devices - Bit8u mode; // transfert mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA + Bit8u mode; // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA Bit16u blksize; // block size Bit8u translation; // type of translation chs_t lchs; // Logical CHS chs_t pchs; // Physical CHS - Bit32u sectors; // Total sectors count + Bit32u sectors_low; // Total sectors count + Bit32u sectors_high; } ata_device_t; typedef struct { @@ -704,10 +692,10 @@ typedef struct { ata_device_t devices[BX_MAX_ATA_DEVICES]; // // map between (bios hd id - 0x80) and ata channels - Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES]; + Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES]; // map between (bios cd id - 0xE0) and ata channels - Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES]; + Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES]; // Buffer for DPTE table dpte_t dpte; @@ -717,9 +705,9 @@ typedef struct { Bit32u trsfbytes; } ata_t; - + #if BX_ELTORITO_BOOT - // ElTorito Device Emulation data + // ElTorito Device Emulation data typedef struct { Bit8u active; Bit8u media; @@ -730,20 +718,20 @@ typedef struct { Bit16u buffer_segment; Bit16u load_segment; Bit16u sector_count; - + // Virtual device chs_t vdevice; } cdemu_t; #endif // BX_ELTORITO_BOOT - + #include "32bitgateway.h" // for access to EBDA area - // The EBDA structure should conform to - // http://www.cybertrails.com/~fys/rombios.htm document + // The EBDA structure should conform to + // http://www.frontiernet.net/~fys/rombios.htm document // I made the ata and cdemu structs begin at 0x121 in the EBDA seg - // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot - // device tables are at 0x9ff00 -- 0x9ffff + // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot + // device tables are at EBDA_SEG:IPL_TABLE_OFFSET typedef struct { unsigned char ebda_size; unsigned char cmos_shutdown_status; @@ -765,7 +753,7 @@ typedef struct { upcall_t upcall; } ebda_data_t; - + #define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1 #define EbdaData ((ebda_data_t *) 0) @@ -779,7 +767,7 @@ typedef struct { Bit32u lba1; Bit32u lba2; } int13ext_t; - + #define Int13Ext ((int13ext_t *) 0) // Disk Physical Table definition @@ -805,7 +793,7 @@ typedef struct { Bit8u reserved3; Bit8u checksum; } dpt_t; - + #define Int13DPT ((dpt_t *) 0) #endif // BX_USE_ATADRV @@ -835,9 +823,9 @@ typedef struct { } r16; struct { Bit32u filler[4]; - Bit8u bl, bh; + Bit8u bl, bh; Bit16u filler1; - Bit8u dl, dh; + Bit8u dl, dh; Bit16u filler2; Bit8u cl, ch; Bit16u filler3; @@ -870,6 +858,14 @@ typedef struct { 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 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 keyboard_panic(); static void shutdown_status_panic(); static void nmi_handler_msg(); - +static void delay_ticks(); +static void delay_ticks_and_check_for_keystroke(); + +static void interactive_bootkey(); static void print_bios_banner(); static void print_boot_device(); static void print_boot_failure(); @@ -964,33 +961,9 @@ Bit16u cdrom_boot(); #endif // BX_ELTORITO_BOOT -static char bios_cvs_version_string[] = "$Revision: 1.138 $"; -static char bios_date_string[] = "$Date: 2005/05/07 15:55:26 $"; - -static char CVSID[] = "$Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $"; - -/* Offset to skip the CVS $Id: prefix */ -#define bios_version_string (CVSID + 4) - -#define BIOS_PRINTF_HALT 1 -#define BIOS_PRINTF_SCREEN 2 -#define BIOS_PRINTF_INFO 4 -#define BIOS_PRINTF_DEBUG 8 -#define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO) -#define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT) - -#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 @@ static struct { { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */ { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */ { 0x5300, 0x532e, none, none, 0x20 }, /* Del */ - { none, none, none, none, none }, /* ??? */ - { none, none, none, none, none }, /* ??? */ - { none, none, none, none, none }, /* ??? */ + { none, none, none, none, none }, + { none, none, none, none, none }, + { 0x565c, 0x567c, none, none, none }, /* \| */ { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */ { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ }; @@ -1422,31 +1395,6 @@ ASM_END ASM_END } -// Bit16u -//get_DS() -//{ -//ASM_START -// mov ax, ds -//ASM_END -//} -// -// void -//set_DS(ds_selector) -// Bit16u ds_selector; -//{ -//ASM_START -// push bp -// mov bp, sp -// -// push ax -// mov ax, 4[bp] ; ds_selector -// mov ds, ax -// pop ax -// -// pop bp -//ASM_END -//} - Bit16u get_SS() { @@ -1462,7 +1410,7 @@ copy_e820_table() Bit8u nr_entries = read_byte(0x9000, 0x1e8); Bit32u base_mem; if (nr_entries > 32) - nr_entries = 32; + nr_entries = 32; write_word(0xe000, 0x8, nr_entries); memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14); /* Report the proper base memory size at address 0x0413: otherwise @@ -1570,7 +1518,7 @@ wrch(c) pop bp ASM_END } - + void send(action, c) Bit16u action; @@ -1626,14 +1574,121 @@ put_uint(action, val, width, neg) send(action, val - (nval * 10) + '0'); } + void +put_luint(action, val, width, neg) + Bit16u action; + unsigned long val; + short width; + bx_bool neg; +{ + unsigned long nval = val / 10; + if (nval) + put_luint(action, nval, width - 1, neg); + else { + while (--width > 0) send(action, ' '); + if (neg) send(action, '-'); + } + send(action, val - (nval * 10) + '0'); +} + +void put_str(action, segment, offset) + Bit16u action; + Bit16u segment; + Bit16u offset; +{ + Bit8u c; + + while (c = read_byte(segment, offset)) { + send(action, c); + offset++; + } +} + + void +delay_ticks(ticks) + Bit16u ticks; +{ + long ticks_to_wait, delta; + Bit32u prev_ticks, t; + + /* + * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. + * We also have to be careful about interrupt storms. + */ +ASM_START + pushf + sti +ASM_END + ticks_to_wait = ticks; + prev_ticks = read_dword(0x0, 0x46c); + do + { +ASM_START + hlt +ASM_END + t = read_dword(0x0, 0x46c); + if (t > prev_ticks) + { + delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ + ticks_to_wait -= delta; + } + else if (t < prev_ticks) + { + ticks_to_wait -= t; /* wrapped */ + } + + prev_ticks = t; + } while (ticks_to_wait > 0); +ASM_START + cli + popf +ASM_END +} + + Bit8u +check_for_keystroke() +{ +ASM_START + mov ax, #0x100 + int #0x16 + jz no_key + mov al, #1 + jmp done +no_key: + xor al, al +done: +ASM_END +} + + Bit8u +get_keystroke() +{ +ASM_START + mov ax, #0x0 + int #0x16 + xchg ah, al +ASM_END +} + + void +delay_ticks_and_check_for_keystroke(ticks, count) + Bit16u ticks, count; +{ + Bit16u i; + for (i = 1; i <= count; i++) { + delay_ticks(ticks); + if (check_for_keystroke()) + break; + } +} + //-------------------------------------------------------------------------- // bios_printf() -// A compact variable argument printf function which prints its output via -// an I/O port so that it can be logged by Bochs/Plex. -// Currently, only %x is supported (or %02x, %04x, etc). +// A compact variable argument printf function. // -// Supports %[format_width][format] -// where format can be d,x,c,s +// Supports %[format_width][length]format +// where format can be x,X,u,d,s,S,c +// and the optional length modifier is l (ell) //-------------------------------------------------------------------------- void bios_printf(action, s) @@ -1644,7 +1699,7 @@ bios_printf(action, s) bx_bool in_format; short i; Bit16u *arg_ptr; - Bit16u arg_seg, arg, nibble, shift_count, format_width; + Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd; arg_ptr = &s; arg_seg = get_SS(); @@ -1671,16 +1726,48 @@ bios_printf(action, s) else { arg_ptr++; // increment to next arg arg = read_word(arg_seg, arg_ptr); - if (c == 'x') { + if (c == 'x' || c == 'X') { if (format_width == 0) format_width = 4; + if (c == 'x') + hexadd = 'a'; + else + hexadd = 'A'; for (i=format_width-1; i>=0; i--) { nibble = (arg >> (4 * i)) & 0x000f; - send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A')); + send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); } } else if (c == 'u') { put_uint(action, arg, format_width, 0); + } + else if (c == 'l') { + s++; + c = read_byte(get_CS(), s); /* is it ld,lx,lu? */ + arg_ptr++; /* increment to next arg */ + hibyte = read_word(arg_seg, arg_ptr); + if (c == 'd') { + if (hibyte & 0x8000) + put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1); + else + put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); + } + else if (c == 'u') { + put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); + } + else if (c == 'x' || c == 'X') + { + if (format_width == 0) + format_width = 8; + if (c == 'x') + hexadd = 'a'; + else + hexadd = 'A'; + for (i=format_width-1; i>=0; i--) { + nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f; + send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); + } + } } else if (c == 'd') { if (arg & 0x8000) @@ -1689,7 +1776,13 @@ bios_printf(action, s) put_int(action, arg, format_width, 0); } else if (c == 's') { - bios_printf(action & (~BIOS_PRINTF_HALT), arg); + put_str(action, get_CS(), arg); + } + else if (c == 'S') { + hibyte = arg; + arg_ptr++; + arg = read_word(arg_seg, arg_ptr); + put_str(action, hibyte, arg); } else if (c == 'c') { send(action, arg); @@ -1706,7 +1799,7 @@ bios_printf(action, s) } if (action & BIOS_PRINTF_HALT) { - // freeze in a busy loop. + // freeze in a busy loop. ASM_START cli halt2_loop: @@ -1740,8 +1833,8 @@ keyboard_init() max = 0x2000; } } - - // Due to timer issues, and if the IPS setting is > 15000000, + + // Due to timer issues, and if the IPS setting is > 15000000, // the incoming keys might not be flushed here. That will // cause a panic a few lines below. See sourceforge bug report : // [ 642031 ] FATAL: Keyboard RESET error:993 @@ -1878,12 +1971,11 @@ keyboard_panic(status) 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 @@ shutdown_status_panic(status) BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status); } +void s3_resume_panic() +{ + BX_PANIC("Returned from s3_resume.\n"); +} + //-------------------------------------------------------------------------- // print_bios_banner // displays a the bios version @@ -1946,74 +2043,84 @@ void void print_bios_banner() { - printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":""); - printf("%s %s\n", bios_cvs_version_string, bios_date_string); + printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ", + BIOS_BUILD_DATE, bios_cvs_version_string); + printf( +#if BX_APM + "apmbios " +#endif +#if BX_PCIBIOS + "pcibios " +#endif +#if BX_ELTORITO_BOOT + "eltorito " +#endif +#if BX_ROMBIOS32 + "rombios32 " +#endif #if BX_TCGBIOS - printf("TCG-enabled BIOS.\n"); + "TCG-enabled" #endif - printf("\n"); + "\n\n"); } - //-------------------------------------------------------------------------- // BIOS Boot Specification 1.0.1 compatibility // -// Very basic support for the BIOS Boot Specification, which allows expansion -// ROMs to register themselves as boot devices, instead of just stealing the +// Very basic support for the BIOS Boot Specification, which allows expansion +// ROMs to register themselves as boot devices, instead of just stealing the // INT 19h boot vector. -// +// // This is a hack: to do it properly requires a proper PnP BIOS and we aren't -// one; we just lie to the option ROMs to make them behave correctly. -// We also don't support letting option ROMs register as bootable disk -// drives (BCVs), only as bootable devices (BEVs). +// one; we just lie to the option ROMs to make them behave correctly. +// We also don't support letting option ROMs register as bootable disk +// drives (BCVs), only as bootable devices (BEVs). // // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm //-------------------------------------------------------------------------- -struct ipl_entry { - Bit16u type; - Bit16u flags; - Bit32u vector; - Bit32u description; - Bit32u reserved; -}; - -static void -init_boot_vectors() +static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"}; + +static void +init_boot_vectors() { - struct ipl_entry e; + ipl_entry_t e; Bit16u count = 0; Bit16u ss = get_SS(); + Bit16u ebda_seg = read_word(0x0040, 0x000E); /* Clear out the IPL table. */ - memsetb(EBDA_SEG, IPL_TABLE_OFFSET, 0, 0xff); + memsetb(ebda_seg, IPL_TABLE_OFFSET, 0, IPL_SIZE); + + /* User selected device not set */ + write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF); /* Floppy drive */ - e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; - memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); + e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; + memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++; /* First HDD */ - e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; - memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); + e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; + memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++; #if BX_ELTORITO_BOOT /* CDROM */ - e.type = 3; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; - memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); + e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; + memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++; -#endif +#endif /* Remember how many devices we have */ - write_word(EBDA_SEG, IPL_COUNT_OFFSET, count); + write_word(ebda_seg, IPL_COUNT_OFFSET, count); /* Not tried booting anything yet */ - write_word(EBDA_SEG, IPL_SEQUENCE_OFFSET, 0xffff); + write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xffff); } static Bit8u get_boot_vector(i, e) -Bit16u i; struct ipl_entry *e; +Bit16u i; ipl_entry_t *e; { Bit16u count; Bit16u ss = get_SS(); @@ -2026,22 +2133,107 @@ Bit16u i; struct ipl_entry *e; return 1; } +#if BX_ELTORITO_BOOT + void +interactive_bootkey() +{ + ipl_entry_t e; + Bit16u count; + char description[33]; + Bit8u scan_code; + Bit8u i; + Bit16u ss = get_SS(); + Bit16u valid_choice = 0; + Bit16u ebda_seg = read_word(0x0040, 0x000E); + + while (check_for_keystroke()) + get_keystroke(); + + printf("\nPress F12 for boot menu.\n\n"); + + delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */ + if (check_for_keystroke()) + { + scan_code = get_keystroke(); + if (scan_code == 0x86) /* F12 */ + { + while (check_for_keystroke()) + get_keystroke(); + + printf("Select boot device:\n\n"); + + count = read_word(ebda_seg, IPL_COUNT_OFFSET); + for (i = 0; i < count; i++) + { + memcpyb(ss, &e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e)); + printf("%d. ", i+1); + switch(e.type) + { + case IPL_TYPE_FLOPPY: + case IPL_TYPE_HARDDISK: + case IPL_TYPE_CDROM: + printf("%s\n", drivetypes[e.type]); + break; + case IPL_TYPE_BEV: + printf("%s", drivetypes[4]); + if (e.description != 0) + { + memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32); + description[32] = 0; + printf(" [%S]", ss, description); + } + printf("\n"); + break; + } + } + + count++; + while (!valid_choice) { + scan_code = get_keystroke(); + if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */ + { + valid_choice = 1; + } + else if (scan_code <= count) + { + valid_choice = 1; + scan_code -= 1; + /* Set user selected device */ + write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, scan_code); + } + } + printf("\n"); + } + } +} +#endif // BX_ELTORITO_BOOT //-------------------------------------------------------------------------- // print_boot_device // displays the boot device //-------------------------------------------------------------------------- -static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"}; - void -print_boot_device(type) +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) print_boot_failure(type, reason) Bit16u type; Bit8u reason; { - if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); + if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); printf("Boot from %s failed", drivetypes[type]); if (type < 4) { /* Report the reason too */ - if (reason==0) - printf(": not a bootable disk"); - else - printf(": could not read the boot disk"); + if (reason==0) + printf(": not a bootable disk"); + else + printf(": could not read the boot disk"); } - printf("\n"); + printf("\n\n"); } //-------------------------------------------------------------------------- @@ -2074,219 +2266,9 @@ print_cdromboot_failure( code ) Bit16u code; { bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code); - + return; } - -#define WAIT_HZ 18 -/** - * Check for keystroke. - * @returns True if keystroke available, False if not. - */ -Bit8u check_for_keystroke() -{ -ASM_START - mov ax, #0x100 - int #0x16 - jz no_key - mov al, #1 - jmp done -no_key: - xor al, al -done: -ASM_END -} - -/** - * Get keystroke. - * @returns BIOS scan code. - */ -Bit8u get_keystroke() -{ -ASM_START - mov ax, #0x0 - int #0x16 - xchg ah, al -ASM_END -} - -/** - * Waits (sleeps) for the given number of ticks. - * Checks for keystroke. - * - * @returns BIOS scan code if available, 0 if not. - * @param ticks Number of ticks to sleep. - * @param stop_on_key Whether to stop immediately upon keypress. - */ -Bit8u wait(ticks, stop_on_key) - Bit16u ticks; - Bit8u stop_on_key; -{ - long ticks_to_wait, delta; - Bit32u prev_ticks, t; - Bit8u scan_code = 0; - - /* - * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. - * We also have to be careful about interrupt storms. - */ - ticks_to_wait = ticks; - prev_ticks = read_dword(0x0, 0x46c); - do - { - t = read_dword(0x0, 0x46c); - if (t > prev_ticks) - { - delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ - ticks_to_wait -= delta; - } - else if (t < prev_ticks) - ticks_to_wait -= t; /* wrapped */ - prev_ticks = t; - - if (check_for_keystroke()) - { - scan_code = get_keystroke(); - bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code); - if (stop_on_key) - return scan_code; - } - } while (ticks_to_wait > 0); - return scan_code; -} - -static void clearscreen() { - /* Hide cursor, clear screen and move cursor to starting position */ -ASM_START - push bx - push cx - push dx - - mov ax, #0x100 - mov cx, #0x1000 - int #0x10 - - mov ax, #0x700 - mov bh, #7 - xor cx, cx - mov dx, #0x184f - int #0x10 - - mov ax, #0x200 - xor bx, bx - xor dx, dx - int #0x10 - - pop dx - pop cx - pop bx -ASM_END -} - -int bootmenu(selected) - int selected; -{ - Bit8u scode; - int max; - Bit16u ebda_seg = read_word(0x0040, 0x000E); - - /* get the number of boot devices */ - max = read_word(ebda_seg, IPL_COUNT_OFFSET); - - for(;;) { - if (selected > max || selected < 1) selected = 1; - clearscreen(); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " Select boot device\n\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 1. Floppy\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 2. Hard drive\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 3. CD-ROM\n"); - if (max == 4) - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 4. Network\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n Currently selected: %d\n", selected); - - do { - scode = wait(WAIT_HZ, 1); - } while (scode == 0); - switch(scode) { - case 0x02: - case 0x03: - case 0x04: - selected = scode - 1; - break; - case 0x05: - if (max == 4) - selected = scode -1 ; - else - scode = 0; - break; - case 0x48: - selected -= 1; - if (selected < 1) - selected = 1; - scode = 0; - break; - case 0x50: - selected += 1; - if (selected > max) - selected = max; - scode = 0; - break; - case 0x1c: - break; - default: - scode = 0; - break; - } - if (scode != 0) - break; - } - - switch (selected) { - case 1: - return 0x3D; - case 2: - return 0x3E; - case 3: - return 0x3F; - case 4: - return 0x58; - default: - return 0; - } -} - -void interactive_bootkey() -{ - Bit16u i; - Bit8u scan = 0; - - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, - "\n\nPress F10 to select boot device.\n"); - - scan = wait(1, 0); - if (scan == 0x44) - scan = bootmenu(inb_cmos(0x3d) & 0x0f); - - /* set the default based on the keypress or menu */ - switch(scan) { - case 0x3D: - outb_cmos(0x3d, 0x01); - break; - case 0x3E: - outb_cmos(0x3d, 0x02); - break; - case 0x3F: - outb_cmos(0x3d, 0x03); - break; - case 0x58: - outb_cmos(0x3d, 0x04); - break; - default: - break; - } -} - void nmi_handler_msg() @@ -2306,7 +2288,7 @@ log_bios_start() #if BX_DEBUG_SERIAL outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */ #endif - BX_INFO("%s\n", bios_version_string); + BX_INFO("%s\n", bios_cvs_version_string); } bx_bool @@ -2341,41 +2323,35 @@ debugger_off() outb(0xfedc, 0x00); } -void +int s3_resume() { Bit32u s3_wakeup_vector; - Bit16u s3_wakeup_ip, s3_wakeup_cs; - Bit8u cmos_shutdown_status; - + Bit8u s3_resume_flag; + + s3_resume_flag = read_byte(0x40, 0xb0); +#ifdef HVMASSIST + s3_wakeup_vector = get_s3_waking_vector(); +#else + s3_wakeup_vector = read_dword(0x40, 0xb2); +#endif + + 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 - 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 + jmpf [0x04b6] ASM_END - - if (cmos_shutdown_status != CMOS_SHUTDOWN_S3) - return; - - 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 + return 1; } #if BX_USE_ATADRV @@ -2425,6 +2401,7 @@ ASM_END // bits 7-4 of the device/head (CB_DH) reg #define ATA_CB_DH_DEV0 0xa0 // select device 0 #define ATA_CB_DH_DEV1 0xb0 // select device 1 +#define ATA_CB_DH_LBA 0x40 // use LBA // status reg (CB_STAT and CB_ASTAT) bits #define ATA_CB_STAT_BSY 0x80 // busy @@ -2474,6 +2451,7 @@ ASM_END #define ATA_CMD_READ_SECTORS 0x20 #define ATA_CMD_READ_VERIFY_SECTORS 0x40 #define ATA_CMD_RECALIBRATE 0x10 +#define ATA_CMD_REQUEST_SENSE 0x03 #define ATA_CMD_SEEK 0x70 #define ATA_CMD_SET_FEATURES 0xEF #define ATA_CMD_SET_MULTIPLE_MODE 0xC6 @@ -2518,7 +2496,7 @@ ASM_END #define ATA_DATA_NO 0x00 #define ATA_DATA_IN 0x01 #define ATA_DATA_OUT 0x02 - + // --------------------------------------------------------------------------- // ATA/ATAPI driver : initialization // --------------------------------------------------------------------------- @@ -2527,7 +2505,7 @@ void ata_init( ) Bit16u ebda_seg=read_word(0x0040,0x000E); Bit8u channel, device; - // Channels info init. + // Channels info init. for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) { write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE); write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0); @@ -2535,7 +2513,7 @@ void ata_init( ) write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0); } - // Devices info init. + // Devices info init. for (device=0; device<BX_MAX_ATA_DEVICES; device++) { write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE); @@ -2550,11 +2528,12 @@ void ata_init( ) write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0); write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0); write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0); - - write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L); + + write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L); + write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L); } - // hdidmap and cdidmap init. + // hdidmap and cdidmap init. for (device=0; device<BX_MAX_ATA_DEVICES; device++) { write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES); write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES); @@ -2562,6 +2541,58 @@ void ata_init( ) 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 @@ void ata_detect( ) // Device detection hdcount=cdcount=0; - + for(device=0; device<BX_MAX_ATA_DEVICES; device++) { Bit16u iobase1, iobase2; Bit8u channel, slave, shift; @@ -2634,33 +2665,34 @@ void ata_detect( ) if ( (sc == 0x55) && (sn == 0xaa) ) { write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN); - + // reset the channel - ata_reset (device); - + ata_reset(device); + // check for ATA or ATAPI outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); sc = inb(iobase1+ATA_CB_SC); sn = inb(iobase1+ATA_CB_SN); - if ( (sc==0x01) && (sn==0x01) ) { + if ((sc==0x01) && (sn==0x01)) { cl = inb(iobase1+ATA_CB_CL); ch = inb(iobase1+ATA_CB_CH); st = inb(iobase1+ATA_CB_STAT); - if ( (cl==0x14) && (ch==0xeb) ) { + if ((cl==0x14) && (ch==0xeb)) { write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI); - } - else if ( (cl==0x00) && (ch==0x00) && (st!=0x00) ) { + } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) { write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA); - } + } else if ((cl==0xff) && (ch==0xff)) { + write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); } } + } type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type); - - // Now we send a IDENTIFY command to ATA device + + // Now we send a IDENTIFY command to ATA device if(type == ATA_TYPE_ATA) { - Bit32u sectors; + Bit32u sectors_low, sectors_high; Bit16u cylinders, heads, spt, blksize; Bit8u translation, removable, mode; @@ -2671,21 +2703,26 @@ void ata_detect( ) write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); - if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, get_SS(),buffer) !=0 ) + if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 ) BX_PANIC("ata-detect: Failed to detect ATA device\n"); removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; -#ifndef NO_PIO32 +#ifndef NO_PIO32 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; #endif - blksize = read_word(get_SS(),buffer+10); - + cylinders = read_word(get_SS(),buffer+(1*2)); // word 1 heads = read_word(get_SS(),buffer+(3*2)); // word 3 spt = read_word(get_SS(),buffer+(6*2)); // word 6 - sectors = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61 + if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support + sectors_low = read_dword(get_SS(),buffer+(100*2)); // word 100 and word 101 + sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and word 103 + } else { + sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61 + sectors_high = 0; + } write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable); @@ -2694,7 +2731,8 @@ void ata_detect( ) write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads); write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders); write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt); - write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors); + write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low); + write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high); BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt); translation = inb_cmos(0x39 + channel/2); @@ -2722,14 +2760,14 @@ void ata_detect( ) break; case ATA_TRANSLATION_LBA: spt = 63; - sectors /= 63; - heads = sectors / 1024; + sectors_low /= 63; + heads = sectors_low / 1024; if (heads>128) heads = 255; else if (heads>64) heads = 128; else if (heads>32) heads = 64; else if (heads>16) heads = 32; else heads=16; - cylinders = sectors / heads; + cylinders = sectors_low / heads; break; case ATA_TRANSLATION_RECHS: // Take care not to overflow @@ -2756,15 +2794,15 @@ void ata_detect( ) write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads); write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders); write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt); - - // fill hdidmap + + // fill hdidmap write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device); hdcount++; } - + // Now we send a IDENTIFY command to ATAPI device if(type == ATA_TYPE_ATAPI) { - + Bit8u type, removable, mode; Bit16u blksize; @@ -2775,12 +2813,12 @@ void ata_detect( ) write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM); write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); - if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, get_SS(),buffer) != 0) + if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0) BX_PANIC("ata-detect: Failed to detect ATAPI device\n"); type = read_byte(get_SS(),buffer+1) & 0x1f; removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; -#ifndef NO_PIO32 +#ifndef NO_PIO32 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; #endif blksize = 2048; @@ -2790,24 +2828,24 @@ void ata_detect( ) write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode); write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize); - // fill cdidmap + // fill cdidmap write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device); cdcount++; } - + { Bit32u sizeinmb; Bit16u ataversion; Bit8u c, i, version, model[41]; - + switch (type) { case ATA_TYPE_ATA: - sizeinmb = read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors); - sizeinmb >>= 11; + sizeinmb = (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21) + | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) >> 11); case ATA_TYPE_ATAPI: // Read ATA/ATAPI version ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160); - for(version=15;version>0;version--) { + for(version=15;version>0;version--) { if((ataversion&(1<<version))!=0) break; } @@ -2816,7 +2854,7 @@ void ata_detect( ) for(i=0;i<20;i++){ write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1)); write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54)); - } + } // Reformat write_byte(get_SS(),model+40,0x00); @@ -2824,7 +2862,13 @@ void ata_detect( ) if(read_byte(get_SS(),model+i)==0x20) write_byte(get_SS(),model+i,0x00); else break; + } + if (i>36) { + write_byte(get_SS(),model+36,0x00); + for(i=35;i>32;i--){ + write_byte(get_SS(),model+i,0x2E); } + } break; } @@ -2832,10 +2876,10 @@ void ata_detect( ) case ATA_TYPE_ATA: printf("ata%d %s: ",channel,slave?" slave":"master"); i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c); - if (sizeinmb < 1UL<<16) - printf(" ATA-%d Hard-Disk (%04u MBytes)\n",version,(Bit16u)sizeinmb); - else - printf(" ATA-%d Hard-Disk (%04u GBytes)\n",version,(Bit16u)(sizeinmb>>10)); + if (sizeinmb < (1UL<<16)) + printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb); + else + printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10)); break; case ATA_TYPE_ATAPI: printf("ata%d %s: ",channel,slave?" slave":"master"); @@ -2856,17 +2900,17 @@ void ata_detect( ) write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount); write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount); write_byte(0x40,0x75, hdcount); - + printf("\n"); // FIXME : should use bios=cmos|auto|disable bits // FIXME : should know about translation bits - // FIXME : move hard_drive_post here - + // FIXME : move hard_drive_post here + } // --------------------------------------------------------------------------- -// ATA/ATAPI driver : software reset +// ATA/ATAPI driver : software reset // --------------------------------------------------------------------------- // ATA-3 // 8.2.1 Software reset - Device 0 @@ -2876,7 +2920,8 @@ Bit16u device; { Bit16u ebda_seg=read_word(0x0040,0x000E); Bit16u iobase1, iobase2; - Bit8u channel, slave, sn, sc; + Bit8u channel, slave, sn, sc; + Bit8u type; Bit16u max; channel = device / 2; @@ -2891,16 +2936,13 @@ Bit16u device; outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST); // 8.2.1 (b) -- wait for BSY - max=0xff; - while(--max>0) { - Bit8u status = inb(iobase1+ATA_CB_STAT); - if ((status & ATA_CB_STAT_BSY) != 0) break; - } + await_ide(BSY, iobase1, 20); // 8.2.1 (f) -- clear SRST outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); - if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_NONE) { + type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type); + if (type != ATA_TYPE_NONE) { // 8.2.1 (g) -- check for sc==sn==0x01 // select device @@ -2909,21 +2951,14 @@ Bit16u device; sn = inb(iobase1+ATA_CB_SN); if ( (sc==0x01) && (sn==0x01) ) { + 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 @@ Bit16u device; } // --------------------------------------------------------------------------- -// ATA/ATAPI driver : execute a non data command +// ATA/ATAPI driver : execute a non data command // --------------------------------------------------------------------------- Bit16u ata_cmd_non_data() @@ -2949,9 +2984,9 @@ Bit16u ata_cmd_non_data() // 5 : more sectors to read/verify // 6 : no sectors left to write // 7 : more sectors to write -Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, segment, offset) +Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset) Bit16u device, command, count, cylinder, head, sector, segment, offset; -Bit32u lba; +Bit32u lba_low, lba_high; { Bit16u ebda_seg=read_word(0x0040,0x000E); Bit16u iobase1, iobase2, blksize; @@ -2980,22 +3015,20 @@ Bit32u lba; // sector will be 0 only on lba access. Convert to lba-chs if (sector == 0) { - if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) { + if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) { outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff); - outb(iobase1 + ATA_CB_SN, lba >> 24); - outb(iobase1 + ATA_CB_CL, 0); - outb(iobase1 + ATA_CB_CH, 0); + outb(iobase1 + ATA_CB_SN, lba_low >> 24); + outb(iobase1 + ATA_CB_CL, lba_high & 0xff); + outb(iobase1 + ATA_CB_CH, lba_high >> 8); command |= 0x04; count &= (1UL << 8) - 1; - lba &= (1UL << 24) - 1; + lba_low &= (1UL << 24) - 1; } - sector = (Bit16u) (lba & 0x000000ffL); - lba >>= 8; - cylinder = (Bit16u) (lba & 0x0000ffffL); - lba >>= 16; - head = ((Bit16u) (lba & 0x0000000fL)) | 0x40; - } + sector = (Bit16u) (lba_low & 0x000000ffL); + cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL); + head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA; + } outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, count); @@ -3005,10 +3038,8 @@ Bit32u lba; outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); outb(iobase1 + ATA_CB_CMD, command); - while (1) { - status = inb(iobase1 + ATA_CB_STAT); - if ( !(status & ATA_CB_STAT_BSY) ) break; - } + await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); + status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_data_in : read error\n"); @@ -3029,12 +3060,12 @@ ASM_START ASM_START push bp mov bp, sp - mov di, _ata_cmd_data_in.offset + 2[bp] - mov ax, _ata_cmd_data_in.segment + 2[bp] - mov cx, _ata_cmd_data_in.blksize + 2[bp] + mov di, _ata_cmd_data_in.offset + 2[bp] + mov ax, _ata_cmd_data_in.segment + 2[bp] + mov cx, _ata_cmd_data_in.blksize + 2[bp] ;; adjust if there will be an overrun. 2K max sector size - cmp di, #0xf800 ;; + cmp di, #0xf800 ;; jbe ata_in_no_adjust ata_in_adjust: @@ -3046,7 +3077,7 @@ ata_in_no_adjust: mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port - mov ah, _ata_cmd_data_in.mode + 2[bp] + mov ah, _ata_cmd_data_in.mode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_in_32 @@ -3068,9 +3099,10 @@ ASM_END current++; write_word(ebda_seg, &EbdaData->ata.trsfsectors,current); count--; + await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); status = inb(iobase1 + ATA_CB_STAT); if (count == 0) { - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) + if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != ATA_CB_STAT_RDY ) { BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status); return 4; @@ -3078,7 +3110,7 @@ ASM_END break; } else { - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) + if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status); return 5; @@ -3103,9 +3135,9 @@ ASM_END // 5 : more sectors to read/verify // 6 : no sectors left to write // 7 : more sectors to write -Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, segment, offset) +Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset) Bit16u device, command, count, cylinder, head, sector, segment, offset; -Bit32u lba; +Bit32u lba_low, lba_high; { Bit16u ebda_seg=read_word(0x0040,0x000E); Bit16u iobase1, iobase2, blksize; @@ -3134,22 +3166,20 @@ Bit32u lba; // sector will be 0 only on lba access. Convert to lba-chs if (sector == 0) { - if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) { + if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) { outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff); - outb(iobase1 + ATA_CB_SN, lba >> 24); - outb(iobase1 + ATA_CB_CL, 0); - outb(iobase1 + ATA_CB_CH, 0); + outb(iobase1 + ATA_CB_SN, lba_low >> 24); + outb(iobase1 + ATA_CB_CL, lba_high & 0xff); + outb(iobase1 + ATA_CB_CH, lba_high >> 8); command |= 0x04; count &= (1UL << 8) - 1; - lba &= (1UL << 24) - 1; + lba_low &= (1UL << 24) - 1; } - sector = (Bit16u) (lba & 0x000000ffL); - lba >>= 8; - cylinder = (Bit16u) (lba & 0x0000ffffL); - lba >>= 16; - head = ((Bit16u) (lba & 0x0000000fL)) | 0x40; - } + sector = (Bit16u) (lba_low & 0x000000ffL); + cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL); + head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA; + } outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, count); @@ -3159,10 +3189,8 @@ Bit32u lba; outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); outb(iobase1 + ATA_CB_CMD, command); - while (1) { - status = inb(iobase1 + ATA_CB_STAT); - if ( !(status & ATA_CB_STAT_BSY) ) break; - } + await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); + status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_data_out : read error\n"); @@ -3183,12 +3211,12 @@ ASM_START ASM_START push bp mov bp, sp - mov si, _ata_cmd_data_out.offset + 2[bp] - mov ax, _ata_cmd_data_out.segment + 2[bp] - mov cx, _ata_cmd_data_out.blksize + 2[bp] + mov si, _ata_cmd_data_out.offset + 2[bp] + mov ax, _ata_cmd_data_out.segment + 2[bp] + mov cx, _ata_cmd_data_out.blksize + 2[bp] ;; adjust if there will be an overrun. 2K max sector size - cmp si, #0xf800 ;; + cmp si, #0xf800 ;; jbe ata_out_no_adjust ata_out_adjust: @@ -3200,7 +3228,7 @@ ata_out_no_adjust: mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port - mov ah, _ata_cmd_data_out.mode + 2[bp] + mov ah, _ata_cmd_data_out.mode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_out_32 @@ -3226,7 +3254,7 @@ ASM_END count--; status = inb(iobase1 + ATA_CB_STAT); if (count == 0) { - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) + if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != ATA_CB_STAT_RDY ) { BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status); return 6; @@ -3234,7 +3262,7 @@ ASM_END break; } else { - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) + if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status); return 7; @@ -3301,19 +3329,17 @@ Bit32u length; if (status & ATA_CB_STAT_BSY) return 2; outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); - // outb(iobase1 + ATA_CB_FR, 0x00); - // outb(iobase1 + ATA_CB_SC, 0x00); - // outb(iobase1 + ATA_CB_SN, 0x00); + outb(iobase1 + ATA_CB_FR, 0x00); + outb(iobase1 + ATA_CB_SC, 0x00); + outb(iobase1 + ATA_CB_SN, 0x00); outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff); outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8); outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET); // Device should ok to receive command - while (1) { - status = inb(iobase1 + ATA_CB_STAT); - if ( !(status & ATA_CB_STAT_BSY) ) break; - } + await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); + status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status); @@ -3330,13 +3356,13 @@ Bit32u length; // Send command to device ASM_START sti ;; enable higher priority interrupts - + push bp mov bp, sp - - mov si, _ata_cmd_packet.cmdoff + 2[bp] - mov ax, _ata_cmd_packet.cmdseg + 2[bp] - mov cx, _ata_cmd_packet.cmdlen + 2[bp] + + mov si, _ata_cmd_packet.cmdoff + 2[bp] + mov ax, _ata_cmd_packet.cmdseg + 2[bp] + mov cx, _ata_cmd_packet.cmdlen + 2[bp] mov es, ax ;; segment in es mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port @@ -3349,32 +3375,38 @@ ASM_END ASM_END if (inout == ATA_DATA_NO) { + await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); status = inb(iobase1 + ATA_CB_STAT); } else { + Bit16u loops = 0; + Bit8u sc; while (1) { + if (loops == 0) {//first time through + status = inb(iobase2 + ATA_CB_ASTAT); + await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); + } + else + await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); + loops++; + status = inb(iobase1 + ATA_CB_STAT); + sc = inb(iobase1 + ATA_CB_SC); // Check if command completed - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break; + if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) && + ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) break; if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status); return 3; } - // Device must be ready to send data - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) - != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { - BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", status); - return 4; - } - // Normalize address bufseg += (bufoff / 16); bufoff %= 16; - + // Get the byte count lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL); @@ -3435,10 +3467,10 @@ ASM_START mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port - mov cx, _ata_cmd_packet.lbefore + 2[bp] + mov cx, _ata_cmd_packet.lbefore + 2[bp] jcxz ata_packet_no_before - mov ah, _ata_cmd_packet.lmode + 2[bp] + mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_before_32 @@ -3455,14 +3487,14 @@ ata_packet_in_before_32_loop: pop eax ata_packet_no_before: - mov cx, _ata_cmd_packet.lcount + 2[bp] + mov cx, _ata_cmd_packet.lcount + 2[bp] jcxz ata_packet_after - mov di, _ata_cmd_packet.bufoff + 2[bp] - mov ax, _ata_cmd_packet.bufseg + 2[bp] + mov di, _ata_cmd_packet.bufoff + 2[bp] + mov ax, _ata_cmd_packet.bufseg + 2[bp] mov es, ax - mov ah, _ata_cmd_packet.lmode + 2[bp] + mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_32 @@ -3476,10 +3508,10 @@ ata_packet_in_32: insd ;; CX dwords transfered to port(DX) to ES:[DI] ata_packet_after: - mov cx, _ata_cmd_packet.lafter + 2[bp] + mov cx, _ata_cmd_packet.lafter + 2[bp] jcxz ata_packet_done - mov ah, _ata_cmd_packet.lmode + 2[bp] + mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_after_32 @@ -3509,7 +3541,7 @@ ASM_END } // Final check, device must be ready - if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) + if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != ATA_CB_STAT_RDY ) { BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status); return 4; @@ -3528,55 +3560,108 @@ ASM_END // Start of ATA/ATAPI generic functions // --------------------------------------------------------------------------- - Bit16u -atapi_get_sense(device) + Bit16u +atapi_get_sense(device, seg, asc, ascq) Bit16u device; { Bit8u atacmd[12]; - Bit8u buffer[16]; + Bit8u buffer[18]; Bit8u i; memsetb(get_SS(),atacmd,0,12); - // Request SENSE - atacmd[0]=0x03; - atacmd[4]=0x20; - if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, get_SS(), buffer) != 0) + // Request SENSE + atacmd[0]=ATA_CMD_REQUEST_SENSE; + atacmd[4]=sizeof(buffer); + if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, get_SS(), buffer) != 0) return 0x0002; - if ((buffer[0] & 0x7e) == 0x70) { - return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12]; - } + write_byte(seg,asc,buffer[12]); + write_byte(seg,ascq,buffer[13]); return 0; } - Bit16u + Bit16u atapi_is_ready(device) Bit16u device; { - Bit8u atacmd[12]; - Bit8u buffer[]; - - 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 @@ static char eltorito[24]="EL TORITO SPEC // // Returns ah: emulated drive, al: error code // - Bit16u + Bit16u cdrom_boot() { Bit16u ebda_seg=read_word(0x0040,0x000E); @@ -3649,9 +3734,12 @@ cdrom_boot() for (device=0; device<BX_MAX_ATA_DEVICES;device++) { if (atapi_is_cdrom(device)) break; } - + // if not found if(device >= BX_MAX_ATA_DEVICES) return 2; + + if(error = atapi_is_ready(device) != 0) + BX_INFO("ata_is_ready returned %d\n",error); // Read the Boot Record Volume Descriptor memsetb(get_SS(),atacmd,0,12); @@ -3672,7 +3760,7 @@ cdrom_boot() } for(i=0;i<23;i++) if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6; - + // ok, now we calculate the Boot catalog address lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47]; @@ -3687,7 +3775,7 @@ cdrom_boot() atacmd[5]=(lba & 0x000000ff); if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) return 7; - + // Validation entry if(buffer[0x00]!=0x01)return 8; // Header if(buffer[0x01]!=0x00)return 9; // Platform @@ -3706,10 +3794,10 @@ cdrom_boot() write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]); if(buffer[0x21]==0){ - // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. + // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. // Win2000 cd boot needs to know it booted from cd write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0); - } + } else if(buffer[0x21]<4) write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00); else @@ -3723,7 +3811,7 @@ cdrom_boot() write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment); write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000); - + nbsectors=buffer[0x27]*0x100+buffer[0x26]; write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors); @@ -3747,7 +3835,6 @@ cdrom_boot() /* measure 1st 512 bytes */ tcpa_ipl((Bit32u)1L,(Bit32u)boot_segment,(Bit32u)0L,(Bit32u)512L); #endif - // Remember the media type switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) { @@ -3769,7 +3856,7 @@ cdrom_boot() case 0x04: // Harddrive write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f); write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders, - (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1); + (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1); write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1); break; } @@ -3782,7 +3869,7 @@ cdrom_boot() write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1); } - + // everything is ok, so from now on, the emulation is active if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) write_byte(ebda_seg,&EbdaData->cdemu.active,0x01); @@ -4128,9 +4215,10 @@ ASM_END regs.u.r8.al = inb_cmos(0x30); regs.u.r8.ah = inb_cmos(0x31); - // limit to 15M - if(regs.u.r16.ax > 0x3c00) - regs.u.r16.ax = 0x3c00; + // According to Ralf Brown's interrupt the limit should be 15M, + // but real machines mostly return max. 63M. + if(regs.u.r16.ax > 0xffc0) + regs.u.r16.ax = 0xffc0; CLEAR_CF(); #endif @@ -4348,13 +4436,35 @@ BX_DEBUG_INT15("case 2:\n"); case 3: // Set Resolution BX_DEBUG_INT15("case 3:\n"); - // BX: + // BH: // 0 = 25 dpi, 1 count per millimeter // 1 = 50 dpi, 2 counts per millimeter // 2 = 100 dpi, 4 counts per millimeter // 3 = 200 dpi, 8 counts per millimeter - CLEAR_CF(); - regs.u.r8.ah = 0; + comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets + if (regs.u.r8.bh < 4) { + ret = send_to_mouse_ctrl(0xE8); // set resolution command + if (ret == 0) { + ret = get_mouse_data(&mouse_data1); + if (mouse_data1 != 0xfa) + BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); + ret = send_to_mouse_ctrl(regs.u.r8.bh); + ret = get_mouse_data(&mouse_data1); + if (mouse_data1 != 0xfa) + BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); + CLEAR_CF(); + regs.u.r8.ah = 0; + } else { + // error + SET_CF(); + regs.u.r8.ah = UNSUPPORTED_FUNCTION; + } + } else { + // error + SET_CF(); + regs.u.r8.ah = UNSUPPORTED_FUNCTION; + } + set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable break; case 4: // Get Device ID @@ -4476,7 +4586,30 @@ BX_DEBUG_INT15("case default:\n"); break; } } -#endif +#endif // BX_USE_PS2_MOUSE + + +void set_e820_range(ES, DI, start, end, type) + Bit16u ES; + Bit16u DI; + Bit32u start; + Bit32u end; + Bit16u type; +{ + write_word(ES, DI, start); + write_word(ES, DI+2, start >> 16); + write_word(ES, DI+4, 0x00); + write_word(ES, DI+6, 0x00); + + end -= start; + write_word(ES, DI+8, end); + write_word(ES, DI+10, end >> 16); + write_word(ES, DI+12, 0x0000); + write_word(ES, DI+14, 0x0000); + + write_word(ES, DI+16, type); + write_word(ES, DI+18, 0x0); +} void int15_function32(regs, ES, DS, FLAGS) @@ -4490,17 +4623,20 @@ BX_DEBUG_INT15("int15 AX=%04x\n",regs.u. switch (regs.u.r8.ah) { case 0x86: - // Wait for CX:DX microseconds. currently using the - // refresh request port 0x61 bit4, toggling every 15usec + // Wait for CX:DX microseconds. currently using the + // refresh request port 0x61 bit4, toggling every 15usec CX = regs.u.r16.cx; DX = regs.u.r16.dx; ASM_START + sti + ;; Get the count in eax - mov ax, .int15_function32.CX [bp] + mov bx, sp + mov ax, _int15_function32.CX [bx] shl eax, #16 - mov ax, .int15_function32.DX [bp] + mov ax, _int15_function32.DX [bx] ;; convert to numbers of 15usec ticks mov ebx, #15 @@ -4531,7 +4667,8 @@ ASM_END case 0xe8: switch(regs.u.r8.al) { - case 0x20: { +#ifdef HVMASSIST + case 0x20: { Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14; if (regs.u.r32.edx != 0x534D4150) /* SMAP */ @@ -4579,7 +4716,7 @@ ASM_END // Get the amount of extended memory (above 1M) regs.u.r8.cl = inb_cmos(0x30); regs.u.r8.ch = inb_cmos(0x31); - + // limit to 15M if (regs.u.r16.cx > (15*1024)) regs.u.r16.cx = 15*1024; @@ -4607,7 +4744,7 @@ ASM_END regs.u.r16.bx = regs.u.r16.dx; break; } - default: /* AH=0xE8?? but not implemented */ + default: /* AH=0xE8?? but not implemented */ goto int15_unimplemented; } break; @@ -4620,16 +4757,178 @@ ASM_END regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; } +#else + case 0x20: // coded by osmaker aka K.J. + if(regs.u.r32.edx == 0x534D4150) + { + extended_memory_size = inb_cmos(0x35); + extended_memory_size <<= 8; + extended_memory_size |= inb_cmos(0x34); + extended_memory_size *= 64; + // greater than EFF00000??? + if(extended_memory_size > 0x3bc000) { + extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000 + } + extended_memory_size *= 1024; + extended_memory_size += (16L * 1024 * 1024); + + if(extended_memory_size <= (16L * 1024 * 1024)) { + extended_memory_size = inb_cmos(0x31); + extended_memory_size <<= 8; + extended_memory_size |= inb_cmos(0x30); + extended_memory_size *= 1024; + extended_memory_size += (1L * 1024 * 1024); + } + + switch(regs.u.r16.bx) + { + case 0: + set_e820_range(ES, regs.u.r16.di, + 0x0000000L, 0x0009f000L, 1); + regs.u.r32.ebx = 1; + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + break; + case 1: + set_e820_range(ES, regs.u.r16.di, + 0x0009f000L, 0x000a0000L, 2); + regs.u.r32.ebx = 2; + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + break; + case 2: + set_e820_range(ES, regs.u.r16.di, + 0x000e8000L, 0x00100000L, 2); + regs.u.r32.ebx = 3; + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + break; + case 3: +#if BX_ROMBIOS32 + set_e820_range(ES, regs.u.r16.di, + 0x00100000L, + extended_memory_size - ACPI_DATA_SIZE, 1); + regs.u.r32.ebx = 4; +#else + set_e820_range(ES, regs.u.r16.di, + 0x00100000L, + extended_memory_size, 1); + regs.u.r32.ebx = 5; +#endif + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + break; + case 4: + set_e820_range(ES, regs.u.r16.di, + extended_memory_size - ACPI_DATA_SIZE, + extended_memory_size, 3); // ACPI RAM + regs.u.r32.ebx = 5; + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + break; + case 5: + /* 256KB BIOS area at the end of 4 GB */ + set_e820_range(ES, regs.u.r16.di, + 0xfffc0000L, 0x00000000L, 2); + regs.u.r32.ebx = 0; + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + default: /* AX=E820, DX=534D4150, BX unrecognized */ + goto int15_unimplemented; + break; + } + } else { + // if DX != 0x534D4150) + goto int15_unimplemented; + } + break; + + case 0x01: + // do we have any reason to fail here ? + CLEAR_CF(); + + // my real system sets ax and bx to 0 + // this is confirmed by Ralph Brown list + // but syslinux v1.48 is known to behave + // strangely if ax is set to 0 + // regs.u.r16.ax = 0; + // regs.u.r16.bx = 0; + + // Get the amount of extended memory (above 1M) + regs.u.r8.cl = inb_cmos(0x30); + regs.u.r8.ch = inb_cmos(0x31); + + // limit to 15M + if(regs.u.r16.cx > 0x3c00) + { + regs.u.r16.cx = 0x3c00; + } + + // Get the amount of extended memory above 16M in 64k blocs + regs.u.r8.dl = inb_cmos(0x34); + regs.u.r8.dh = inb_cmos(0x35); + + // Set configured memory equal to extended memory + regs.u.r16.ax = regs.u.r16.cx; + regs.u.r16.bx = regs.u.r16.dx; + break; + default: /* AH=0xE8?? but not implemented */ + goto int15_unimplemented; + } + break; + int15_unimplemented: + // fall into the default + default: + BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", + (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); + SET_CF(); + regs.u.r8.ah = UNSUPPORTED_FUNCTION; + break; + } +#endif /* HVMASSIST */ } void int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS) Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS; { - Bit8u scan_code, ascii_code, shift_flags, count; + Bit8u scan_code, ascii_code, shift_flags, led_flags, count; Bit16u kbd_code, max; BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX); + + shift_flags = read_byte(0x0040, 0x17); + led_flags = read_byte(0x0040, 0x97); + if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) { +ASM_START + cli +ASM_END + outb(0x60, 0xed); + while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21); + if ((inb(0x60) == 0xfa)) { + led_flags &= 0xf8; + led_flags |= ((shift_flags >> 4) & 0x07); + outb(0x60, led_flags & 0x07); + while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21); + inb(0x60); + write_byte(0x0040, 0x97, led_flags); + } +ASM_START + sti +ASM_END + } switch (GET_AH()) { case 0x00: /* read keyboard input */ @@ -4668,7 +4967,7 @@ int16_function(DI, SI, BP, SP, BX, DX, C break; case 0x09: /* GET KEYBOARD FUNCTIONALITY */ - // bit Bochs Description + // bit Bochs Description // 7 0 reserved // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support) // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support) @@ -4698,7 +4997,7 @@ int16_function(DI, SI, BP, SP, BX, DX, C kbd_code |= (inb(0x60) << 8); } } while (--count>0); - } + } } BX=kbd_code; break; @@ -4725,7 +5024,8 @@ int16_function(DI, SI, BP, SP, BX, DX, C case 0x12: /* get extended keyboard status */ shift_flags = read_byte(0x0040, 0x17); SET_AL(shift_flags); - shift_flags = read_byte(0x0040, 0x18); + shift_flags = read_byte(0x0040, 0x18) & 0x73; + shift_flags |= read_byte(0x0040, 0x96) & 0x0c; SET_AH(shift_flags); BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); break; @@ -4740,7 +5040,7 @@ int16_function(DI, SI, BP, SP, BX, DX, C case 0x6F: if (GET_AL() == 0x08) - SET_AH(0x02); // unsupported, aka normal keyboard + SET_AH(0x02); // unsupported, aka normal keyboard default: BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH()); @@ -4881,7 +5181,7 @@ int09_function(DI, SI, BP, SP, BX, DX, C Bit16u DI, SI, BP, SP, BX, DX, CX, AX; { Bit8u scancode, asciicode, shift_flags; - Bit8u mf2_flags, mf2_state, led_flags; + Bit8u mf2_flags, mf2_state; // // DS has been set to F000 before call @@ -4899,7 +5199,6 @@ int09_function(DI, SI, BP, SP, BX, DX, C shift_flags = read_byte(0x0040, 0x17); mf2_flags = read_byte(0x0040, 0x18); mf2_state = read_byte(0x0040, 0x96); - led_flags = read_byte(0x0040, 0x97); asciicode = 0; switch (scancode) { @@ -4908,8 +5207,6 @@ int09_function(DI, SI, BP, SP, BX, DX, C write_byte(0x0040, 0x17, shift_flags); mf2_flags |= 0x40; write_byte(0x0040, 0x18, mf2_flags); - led_flags ^= 0x04; - write_byte(0x0040, 0x97, led_flags); break; case 0xba: /* Caps Lock release */ mf2_flags &= ~0x40; @@ -4917,11 +5214,8 @@ int09_function(DI, SI, BP, SP, BX, DX, C break; case 0x2a: /* L Shift press */ - /*shift_flags &= ~0x40;*/ shift_flags |= 0x02; write_byte(0x0040, 0x17, shift_flags); - led_flags &= ~0x04; - write_byte(0x0040, 0x97, led_flags); break; case 0xaa: /* L Shift release */ shift_flags &= ~0x02; @@ -4929,11 +5223,8 @@ int09_function(DI, SI, BP, SP, BX, DX, C break; case 0x36: /* R Shift press */ - /*shift_flags &= ~0x40;*/ shift_flags |= 0x01; write_byte(0x0040, 0x17, shift_flags); - led_flags &= ~0x04; - write_byte(0x0040, 0x97, led_flags); break; case 0xb6: /* R Shift release */ shift_flags &= ~0x01; @@ -4941,71 +5232,75 @@ int09_function(DI, SI, BP, SP, BX, DX, C break; case 0x1d: /* Ctrl press */ - shift_flags |= 0x04; - write_byte(0x0040, 0x17, shift_flags); - if (mf2_state & 0x01) { - mf2_flags |= 0x04; - } else { - mf2_flags |= 0x01; + if ((mf2_state & 0x01) == 0) { + shift_flags |= 0x04; + write_byte(0x0040, 0x17, shift_flags); + if (mf2_state & 0x02) { + mf2_state |= 0x04; + write_byte(0x0040, 0x96, mf2_state); + } else { + mf2_flags |= 0x01; + write_byte(0x0040, 0x18, mf2_flags); } - write_byte(0x0040, 0x18, mf2_flags); + } break; case 0x9d: /* Ctrl release */ - shift_flags &= ~0x04; - write_byte(0x0040, 0x17, shift_flags); - if (mf2_state & 0x01) { - mf2_flags &= ~0x04; - } else { - mf2_flags &= ~0x01; + if ((mf2_state & 0x01) == 0) { + shift_flags &= ~0x04; + write_byte(0x0040, 0x17, shift_flags); + if (mf2_state & 0x02) { + mf2_state &= ~0x04; + write_byte(0x0040, 0x96, mf2_state); + } else { + mf2_flags &= ~0x01; + write_byte(0x0040, 0x18, mf2_flags); } - write_byte(0x0040, 0x18, mf2_flags); + } break; case 0x38: /* Alt press */ shift_flags |= 0x08; write_byte(0x0040, 0x17, shift_flags); - if (mf2_state & 0x01) { - mf2_flags |= 0x08; + if (mf2_state & 0x02) { + mf2_state |= 0x08; + write_byte(0x0040, 0x96, mf2_state); } else { mf2_flags |= 0x02; - } - write_byte(0x0040, 0x18, mf2_flags); + write_byte(0x0040, 0x18, mf2_flags); + } break; case 0xb8: /* Alt release */ shift_flags &= ~0x08; write_byte(0x0040, 0x17, shift_flags); - if (mf2_state & 0x01) { - mf2_flags &= ~0x08; + if (mf2_state & 0x02) { + mf2_state &= ~0x08; + write_byte(0x0040, 0x96, mf2_state); } else { mf2_flags &= ~0x02; - } - write_byte(0x0040, 0x18, mf2_flags); + write_byte(0x0040, 0x18, mf2_flags); + } break; case 0x45: /* Num Lock press */ - if ((mf2_state & 0x01) == 0) { + if ((mf2_state & 0x03) == 0) { mf2_flags |= 0x20; write_byte(0x0040, 0x18, mf2_flags); shift_flags ^= 0x20; - led_flags ^= 0x02; write_byte(0x0040, 0x17, shift_flags); - write_byte(0x0040, 0x97, led_flags); - } + } break; case 0xc5: /* Num Lock release */ - if ((mf2_state & 0x01) == 0) { + if ((mf2_state & 0x03) == 0) { mf2_flags &= ~0x20; write_byte(0x0040, 0x18, mf2_flags); - } + } break; case 0x46: /* Scroll Lock press */ mf2_flags |= 0x10; write_byte(0x0040, 0x18, mf2_flags); shift_flags ^= 0x10; - led_flags ^= 0x01; write_byte(0x0040, 0x17, shift_flags); - write_byte(0x0040, 0x97, led_flags); break; case 0xc6: /* Scroll Lock release */ @@ -5018,50 +5313,55 @@ int09_function(DI, SI, BP, SP, BX, DX, C machine_reset(); /* Fall through */ default: - if (scancode & 0x80) return; /* toss key releases ... */ + if (scancode & 0x80) { + break; /* toss key releases ... */ + } if (scancode > MAX_SCAN_CODE) { - BX_INFO("KBD: int09h_handler(): unknown scancode (%x) read!\n", scancode); + BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode); return; - } + } if (shift_flags & 0x08) { /* ALT */ asciicode = scan_to_scanascii[scancode].alt; scancode = scan_to_scanascii[scancode].alt >> 8; - } - else if (shift_flags & 0x04) { /* CONTROL */ + } else if (shift_flags & 0x04) { /* CONTROL */ asciicode = scan_to_scanascii[scancode].control; scancode = scan_to_scanascii[scancode].control >> 8; - } - else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */ - /* check if lock state should be ignored + } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) { + /* extended keys handling */ + asciicode = 0xe0; + scancode = scan_to_scanascii[scancode].normal >> 8; + } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */ + /* check if lock state should be ignored * because a SHIFT key are pressed */ - + if (shift_flags & scan_to_scanascii[scancode].lock_flags) { asciicode = scan_to_scanascii[scancode].normal; scancode = scan_to_scanascii[scancode].normal >> 8; - } - else { + } else { asciicode = scan_to_scanascii[scancode].shift; scancode = scan_to_scanascii[scancode].shift >> 8; - } } - else { + } else { /* check if lock is on */ if (shift_flags & scan_to_scanascii[scancode].lock_flags) { asciicode = scan_to_scanascii[scancode].shift; scancode = scan_to_scanascii[scancode].shift >> 8; - } - else { + } else { asciicode = scan_to_scanascii[scancode].normal; scancode = scan_to_scanascii[scancode].normal >> 8; - } } + } if (scancode==0 && asciicode==0) { BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n"); - } + } enqueue_key(scancode, asciicode); break; - } - mf2_state &= ~0x01; + } + if ((scancode & 0x7f) != 0x1d) { + mf2_state &= ~0x01; + } + mf2_state &= ~0x02; + write_byte(0x0040, 0x96, mf2_state); } unsigned int @@ -5069,9 +5369,6 @@ enqueue_key(scan_code, ascii_code) 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 @@ BX_DEBUG_INT74("int74: read byte %02x\n" mouse_flags_2 = read_byte(ebda_seg, 0x0027); if ( (mouse_flags_2 & 0x80) != 0x80 ) { - // BX_PANIC("int74_function:\n"); return; - } + } package_count = mouse_flags_2 & 0x07; index = mouse_flags_1 & 0x07; @@ -5152,10 +5448,10 @@ BX_DEBUG_INT74("int74_function: make_far #if BX_USE_ATADRV void -int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) - Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; +int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) + Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { - Bit32u lba; + Bit32u lba_low, lba_high; Bit16u ebda_seg=read_word(0x0040,0x000E); Bit16u cylinder, head, sector; Bit16u segment, offset; @@ -5176,12 +5472,12 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, // Get the ata channel device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]); - // basic check : device has to be valid + // basic check : device has to be valid if (device >= BX_MAX_ATA_DEVICES) { BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); goto int13_fail; } - + switch (GET_AH()) { case 0x00: /* disk controller reset */ @@ -5199,7 +5495,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, break; case 0x02: // read disk sectors - case 0x03: // write disk sectors + case 0x03: // write disk sectors case 0x04: // verify disk sectors count = GET_AL(); @@ -5211,10 +5507,10 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, segment = ES; offset = BX; - if ( (count > 128) || (count == 0) ) { - BX_INFO("int13_harddisk: function %02x, count out of range!\n",GET_AH()); + if ((count > 128) || (count == 0) || (sector == 0)) { + BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH()); goto int13_fail; - } + } nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); @@ -5225,7 +5521,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector); goto int13_fail; } - + // FIXME verify if ( GET_AH() == 0x04 ) goto int13_success; @@ -5234,14 +5530,15 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, // if needed, translate lchs to lba, and execute command if ( (nph != nlh) || (npspt != nlspt)) { - lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1; + lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1; + lba_high = 0; sector = 0; // this forces the command to be lba } if ( GET_AH() == 0x02 ) - status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba, segment, offset); + status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset); else - status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, segment, offset); + status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset); // Set nb of sector transferred SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors)); @@ -5262,7 +5559,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, break; case 0x08: /* read disk drive parameters */ - + // Get logical geometry from table nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); @@ -5277,13 +5574,13 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, SET_DL(count); /* FIXME returns 0, 1, or n hard drives */ // FIXME should set ES & DI - + goto int13_success; break; case 0x10: /* check drive ready */ // should look at 40:8E also??? - + // Read the status from controller status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT); if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) { @@ -5297,15 +5594,15 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, 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,30 +5623,31 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, count=read_word(DS, SI+(Bit16u)&Int13Ext->count); segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment); offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset); - - // Can't use 64 bits lba - lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); - if (lba != 0L) { - BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH()); - goto int13_fail; - } - - // Get 32 bits lba and check - lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); - if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) { + + // Get 32 msb lba and check + lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); + if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) { BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); goto int13_fail; } + // Get 32 lsb lba and check + lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); + if (lba_high == read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) + && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) { + BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); + goto int13_fail; + } + // If verify or seek if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) goto int13_success; - + // Execute the command if ( GET_AH() == 0x42 ) - status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba, segment, offset); + status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset); else - status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset); + status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset); count=read_word(ebda_seg, &EbdaData->ata.trsfsectors); write_word(DS, SI+(Bit16u)&Int13Ext->count, count); @@ -5367,7 +5665,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, case 0x49: // IBM/MS extended media change goto int13_success; // Always success for HD break; - + case 0x46: // IBM/MS eject media SET_AH(0xb2); // Volume Not Removable goto int13_fail_noah; // Always fail for HD @@ -5377,7 +5675,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, size=read_word(DS,SI+(Bit16u)&Int13DPT->size); // Buffer is too small - if(size < 0x1a) + if(size < 0x1a) goto int13_fail; // EDD 1.x @@ -5387,17 +5685,26 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders); nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads); npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt); - lba = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors); + lba_low = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low); + lba_high = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high); blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a); - write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid - write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc); + if (lba_high || (lba_low/npspt)/nph > 0x3fff) + { + write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is invalid + write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff); + } + else + { + write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid + write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc); + } write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph); write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt); - write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba); // FIXME should be Bit64 - write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L); - write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); + write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low); + write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high); + write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); } // EDD 2.x @@ -5407,8 +5714,8 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e); - write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); - write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); + write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); + write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); // Fill in dpte channel = device / 2; @@ -5418,14 +5725,14 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation); - options = (translation==ATA_TRANSLATION_NONE?0:1<<3); // chs translation + options = (translation==ATA_TRANSLATION_NONE?0:1)<<3; // chs translation options |= (1<<4); // lba translation - options |= (mode==ATA_MODE_PIO32?1:0<<7); - options |= (translation==ATA_TRANSLATION_LBA?1:0<<9); - options |= (translation==ATA_TRANSLATION_RECHS?3:0<<9); + options |= (mode==ATA_MODE_PIO32?1:0)<<7; + options |= (translation==ATA_TRANSLATION_LBA?1:0)<<9; + options |= (translation==ATA_TRANSLATION_RECHS?3:0)<<9; write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1); - write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2); + write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC); write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb ); write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq ); @@ -5434,10 +5741,13 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 ); write_word(ebda_seg, &EbdaData->ata.dpte.options, options); write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0); - write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); - + if (size >=0x42) + write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); + else + write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10); + checksum=0; - for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i); + for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i); checksum = ~checksum; write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum); } @@ -5463,7 +5773,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A'); write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0); } - else { + else { // FIXME PCI } write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A'); @@ -5476,7 +5786,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0); write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L); } - else { + else { // FIXME PCI } write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2); @@ -5512,7 +5822,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, case 0x0d: /* alternate disk reset */ case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ - BX_INFO("int13h_harddisk function %02xh unimplemented, returns success\n", GET_AH()); + BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH()); goto int13_success; break; @@ -5521,7 +5831,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX, case 0x18: // set media type for format case 0x50: // IBM/MS send packet command default: - BX_INFO("int13_harddisk function %02xh unsupported, returns fail\n", GET_AH()); + BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH()); goto int13_fail; break; } @@ -5557,8 +5867,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL Bit16u count, segment, offset, i, size; BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); - // BX_DEBUG_INT13_CD("int13_cdrom: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI); - + SET_DISK_RET_STATUS(0x00); /* basic check : device should be 0xE0+ */ @@ -5575,16 +5884,16 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); goto int13_fail; } - + switch (GET_AH()) { // all those functions return SUCCESS case 0x00: /* disk controller reset */ case 0x09: /* initialize drive parameters */ case 0x0c: /* seek to specified cylinder */ - case 0x0d: /* alternate disk reset */ - case 0x10: /* check drive ready */ - case 0x11: /* recalibrate */ + case 0x0d: /* alternate disk reset */ + case 0x10: /* check drive ready */ + case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ case 0x16: /* detect disk change */ goto int13_success; @@ -5606,7 +5915,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL /* set CF if error status read */ if (status) goto int13_fail_nostatus; else goto int13_success_noah; - break; + break; case 0x15: /* read disk drive size */ SET_AH(0x02); @@ -5623,11 +5932,11 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL case 0x42: // IBM/MS extended read case 0x44: // IBM/MS verify sectors case 0x47: // IBM/MS extended seek - + count=read_word(DS, SI+(Bit16u)&Int13Ext->count); segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment); offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset); - + // Can't use 64 bits lba lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); if (lba != 0L) { @@ -5635,13 +5944,13 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL goto int13_fail; } - // Get 32 bits lba + // Get 32 bits lba lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); // If verify or seek if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) goto int13_success; - + memsetb(get_SS(),atacmd,0,12); atacmd[0]=0x28; // READ command atacmd[7]=(count & 0xff00) >> 8; // Sectors @@ -5650,7 +5959,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL atacmd[3]=(lba & 0x00ff0000) >> 16; atacmd[4]=(lba & 0x0000ff00) >> 8; atacmd[5]=(lba & 0x000000ff); - status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset); + status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset); count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11); write_word(DS, SI+(Bit16u)&Int13Ext->count, count); @@ -5697,21 +6006,21 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL case 0x46: // IBM/MS eject media locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock); - + if (locks != 0) { SET_AH(0xb1); // media locked goto int13_fail_noah; } // FIXME should handle 0x31 no media in device // FIXME should handle 0xb5 valid request failed - + // Call removable media eject ASM_START push bp mov bp, sp mov ah, #0x52 - int 15 + int #0x15 mov _int13_cdrom.status + 2[bp], ah jnc int13_cdrom_rme_end mov _int13_cdrom.status, #1 @@ -5731,7 +6040,7 @@ int13_cdrom_rme_end: size = read_word(DS,SI+(Bit16u)&Int13Ext->size); // Buffer is too small - if(size < 0x1a) + if(size < 0x1a) goto int13_fail; // EDD 1.x @@ -5746,8 +6055,8 @@ int13_cdrom_rme_end: write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff); write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff); write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); // FIXME should be Bit64 - write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff); - write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); + write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff); + write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); } // EDD 2.x @@ -5757,8 +6066,8 @@ int13_cdrom_rme_end: write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e); - write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); - write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); + write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); + write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); // Fill in dpte channel = device / 2; @@ -5774,7 +6083,7 @@ int13_cdrom_rme_end: options |= (mode==ATA_MODE_PIO32?1:0<<7); write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1); - write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2); + write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC); write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb ); write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq ); @@ -5786,7 +6095,7 @@ int13_cdrom_rme_end: write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); checksum=0; - for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i); + for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i); checksum = ~checksum; write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum); } @@ -5812,7 +6121,7 @@ int13_cdrom_rme_end: write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A'); write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0); } - else { + else { // FIXME PCI } write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A'); @@ -5825,7 +6134,7 @@ int13_cdrom_rme_end: write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0); write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L); } - else { + else { // FIXME PCI } write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2); @@ -5847,7 +6156,7 @@ int13_cdrom_rme_end: SET_AH(06); goto int13_fail_nostatus; break; - + case 0x4e: // // IBM/MS set hardware configuration // DMA, prefetch, PIO maximum not supported switch (GET_AL()) { @@ -5909,7 +6218,7 @@ int13_eltorito(DS, ES, DI, SI, BP, SP, B BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI); - + switch (GET_AH()) { // FIXME ElTorito Various. Should be implemented @@ -5984,11 +6293,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, Bit8u atacmd[12]; BX_DEBUG_INT13_ET("int13_cdemu: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); - //BX_DEBUG_INT13_ET("int13_cdemu: SS=%04x ES=%04x DI=%04x SI=%04x\n", get_SS(), ES, DI, SI); - + /* at this point, we are emulating a floppy/harddisk */ - - // Recompute the device number + + // Recompute the device number device = read_byte(ebda_seg,&EbdaData->cdemu.controller_index) * 2; device += read_byte(ebda_seg,&EbdaData->cdemu.device_spec); @@ -6001,7 +6309,6 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, goto int13_fail; } - switch (GET_AH()) { // all those functions return SUCCESS @@ -6010,7 +6317,7 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, case 0x0c: /* seek to specified cylinder */ case 0x0d: /* alternate disk reset */ // FIXME ElTorito Various. should really reset ? case 0x10: /* check drive ready */ // FIXME ElTorito Various. should check if ready ? - case 0x11: /* recalibrate */ + case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ case 0x16: /* detect disk change */ goto int13_success; @@ -6035,9 +6342,9 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, case 0x02: // read disk sectors case 0x04: // verify disk sectors - vspt = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); - vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders); - vheads = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads); + vspt = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); + vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders); + vheads = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads); ilba = read_dword(ebda_seg,&EbdaData->cdemu.ilba); @@ -6066,17 +6373,17 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, // calculate the virtual lba inside the image vlba=((((Bit32u)cylinder*(Bit32u)vheads)+(Bit32u)head)*(Bit32u)vspt)+((Bit32u)(sector-1)); - + // In advance so we don't loose the count SET_AL(nbsectors); // start lba on cd - slba = (Bit32u)vlba/4; + slba = (Bit32u)vlba/4; before= (Bit16u)vlba%4; // end lba on cd elba = (Bit32u)(vlba+nbsectors-1)/4; - + memsetb(get_SS(),atacmd,0,12); atacmd[0]=0x28; // READ command atacmd[7]=((Bit16u)(elba-slba+1) & 0xff00) >> 8; // Sectors @@ -6096,10 +6403,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, break; case 0x08: /* read disk drive parameters */ - vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); - vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1; - vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1; - + vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); + vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1; + vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1; + SET_AL( 0x00 ); SET_BL( 0x00 ); SET_CH( vcylinders & 0xff ); @@ -6107,7 +6414,7 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, SET_DH( vheads ); SET_DL( 0x02 ); // FIXME ElTorito Various. should send the real count of drives 1 or 2 // FIXME ElTorito Harddisk. should send the HD count - + switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) { case 0x01: SET_BL( 0x02 ); break; case 0x02: SET_BL( 0x04 ); break; @@ -6143,7 +6450,7 @@ ASM_END case 0x45: // IBM/MS lock/unlock drive case 0x46: // IBM/MS eject media case 0x47: // IBM/MS extended seek - case 0x48: // IBM/MS get drive parameters + case 0x48: // IBM/MS get drive parameters case 0x49: // IBM/MS extended media change case 0x4e: // ? - set hardware configuration case 0x50: // ? - send packet command @@ -6231,8 +6538,8 @@ ASM_END } void -int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) - Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; +int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) + Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { Bit8u drive, num_sectors, sector, head, status, mod; Bit8u drive_map; @@ -6338,7 +6645,7 @@ BX_DEBUG_INT13_HD("int13_f01\n"); } if ( (num_sectors > 128) || (num_sectors == 0) ) - BX_PANIC("int13_harddisk(): num_sectors out of range!\n"); + BX_PANIC("int13_harddisk: num_sectors out of range!\n"); if (head > 15) BX_PANIC("hard drive BIOS:(read/verify) head > 15\n"); @@ -6484,7 +6791,7 @@ BX_DEBUG_INT13_HD("int13_f03\n"); } if ( (num_sectors > 128) || (num_sectors == 0) ) - BX_PANIC("int13_harddisk(): num_sectors out of range!\n"); + BX_PANIC("int13_harddisk: num_sectors out of range!\n"); if (head > 15) BX_PANIC("hard drive BIOS:(read) head > 15\n"); @@ -6594,7 +6901,7 @@ BX_DEBUG_INT13_HD("int13_f05\n"); case 0x08: /* read disk drive parameters */ BX_DEBUG_INT13_HD("int13_f08\n"); - + drive = GET_ELDL (); get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); @@ -6734,10 +7041,10 @@ ASM_END break; case 0x18: // set media type for format - case 0x41: // IBM/MS - case 0x42: // IBM/MS - case 0x43: // IBM/MS - case 0x44: // IBM/MS + case 0x41: // IBM/MS + case 0x42: // IBM/MS + case 0x43: // IBM/MS + case 0x44: // IBM/MS case 0x45: // IBM/MS lock/unlock drive case 0x46: // IBM/MS eject media case 0x47: // IBM/MS extended seek @@ -6782,7 +7089,7 @@ get_hd_geometry(drive, hd_cylinders, hd_ 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 @@ get_hd_geometry(drive, hd_cylinders, hd_ #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 @@ floppy_media_sense(drive) retval = 1; } // - // Extended floppy size uses special cmos setting + // Extended floppy size uses special cmos setting else if ( drive_type == 6 ) { // 160k 5.25" drive config_data = 0x00; // 0000 0000 @@ -6953,63 +7321,41 @@ floppy_drive_recal(drive) floppy_drive_recal(drive) Bit16u drive; { - Bit8u val8, dor; + Bit8u val8; Bit16u curr_cyl_offset; - // set 40:3e bit 7 to 0 - val8 = read_byte(0x0000, 0x043e); - val8 &= 0x7f; - write_byte(0x0000, 0x043e, val8); - - // turn on motor of selected drive, DMA & int enabled, normal operation - if (drive) - dor = 0x20; - else - dor = 0x10; - dor |= 0x0c; - dor |= drive; - outb(0x03f2, dor); - - // reset the disk motor timeout value of INT 08 - write_byte(0x40,0x40, BX_FLOPPY_ON_CNT); - - // check port 3f4 for drive readiness - val8 = inb(0x3f4); - if ( (val8 & 0xf0) != 0x80 ) - BX_PANIC("floppy recal:f07: ctrl not ready\n"); + floppy_prepare_controller(drive); // send Recalibrate command (2 bytes) to controller outb(0x03f5, 0x07); // 07: Recalibrate outb(0x03f5, drive); // 0=drive0, 1=drive1 - // turn on interrupts + // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 - val8 = (read_byte(0x0000, 0x043e) & 0x80); - while ( val8 == 0 ) { - val8 = (read_byte(0x0000, 0x043e) & 0x80); - } - - 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 @@ floppy_drive_exists(drive) return(1); } -#if BX_SUPPORT_FLOPPY void int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; @@ -7049,7 +7394,6 @@ int13_diskette_function(DS, ES, DI, SI, Bit16u es, last_addr; BX_DEBUG_INT13_FL("int13_diskette: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); - // BX_DEBUG_INT13_FL("int13_diskette: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), get_DS(), ES, DI, SI); ah = GET_AH(); @@ -7062,7 +7406,7 @@ BX_DEBUG_INT13_FL("floppy f00\n"); set_diskette_ret_status(1); SET_CF(); return; - } + } drive_type = inb_cmos(0x10); if (drive == 0) @@ -7074,7 +7418,7 @@ BX_DEBUG_INT13_FL("floppy f00\n"); set_diskette_ret_status(0x80); SET_CF(); return; - } + } SET_AH(0); set_diskette_ret_status(0); CLEAR_CF(); // successful @@ -7087,7 +7431,7 @@ BX_DEBUG_INT13_FL("floppy f00\n"); SET_AH(val8); if (val8) { SET_CF(); - } + } return; case 0x02: // Read Diskette Sectors @@ -7099,15 +7443,15 @@ BX_DEBUG_INT13_FL("floppy f00\n"); head = GET_DH(); drive = GET_ELDL(); - if ( (drive > 1) || (head > 1) || - (num_sectors == 0) || (num_sectors > 72) ) { -BX_INFO("floppy: drive>1 || head>1 ...\n"); + if ((drive > 1) || (head > 1) || (sector == 0) || + (num_sectors == 0) || (num_sectors > 72)) { + BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); SET_AH(1); set_diskette_ret_status(1); SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } + } // see if drive exists if (floppy_drive_exists(drive) == 0) { @@ -7116,7 +7460,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } + } // see if media in drive, and type is known if (floppy_media_known(drive) == 0) { @@ -7126,8 +7470,8 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } } + } if (ah == 0x02) { // Read Diskette Sectors @@ -7146,7 +7490,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n if ( base_address < base_es ) { // in case of carry, adjust page by 1 page++; - } + } base_count = (num_sectors * 512) - 1; // check for 64K boundary overrun @@ -7157,7 +7501,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } + } BX_DEBUG_INT13_FL("masking DMA-1 c2\n"); outb(0x000a, 0x06); @@ -7190,28 +7534,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n //-------------------------------------- // set up floppy controller for transfer //-------------------------------------- - - // set 40:3e bit 7 to 0 - val8 = read_byte(0x0000, 0x043e); - val8 &= 0x7f; - write_byte(0x0000, 0x043e, val8); - - // turn on motor of selected drive, DMA & int enabled, normal operation - if (drive) - dor = 0x20; - else - dor = 0x10; - dor |= 0x0c; - dor |= drive; - outb(0x03f2, dor); - - // reset the disk motor timeout value of INT 08 - write_byte(0x40,0x40, BX_FLOPPY_ON_CNT); - - // check port 3f4 for drive readiness - val8 = inb(0x3f4); - if ( (val8 & 0xf0) != 0x80 ) - BX_PANIC("int13_diskette:f02: ctrl not ready\n"); + floppy_prepare_controller(drive); // send read-normal-data command (9 bytes) to controller outb(0x03f5, 0xe6); // e6: read normal data @@ -7224,27 +7547,35 @@ BX_INFO("floppy: drive>1 || head>1 ...\n outb(0x03f5, 0); // Gap length outb(0x03f5, 0xff); // Gap length - // turn on interrupts + // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 - val8 = (read_byte(0x0000, 0x043e) & 0x80); - while ( val8 == 0 ) { - val8 = (read_byte(0x0000, 0x043e) & 0x80); + do { + val8 = read_byte(0x0040, 0x0040); + if (val8 == 0) { + floppy_reset_controller(); + SET_AH(0x80); // drive not ready (timeout) + set_diskette_ret_status(0x80); + SET_AL(0); // no sectors read + SET_CF(); // error occurred + return; } - - val8 = 0; // separate asm from while() loop - // turn off interrupts + val8 = (read_byte(0x0040, 0x003e) & 0x80); + } while ( val8 == 0 ); + + val8 = 0; // separate asm from while() loop + // turn off interrupts ASM_START cli ASM_END // set 40:3e bit 7 to 0 - val8 = read_byte(0x0000, 0x043e); + val8 = read_byte(0x0040, 0x003e); val8 &= 0x7f; - write_byte(0x0000, 0x043e, val8); + write_byte(0x0040, 0x003e, val8); // check port 3f4 for accessibility to status bytes val8 = inb(0x3f4); @@ -7275,7 +7606,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } + } // ??? should track be new val from return_status[3] ? set_diskette_current_cyl(drive, track); @@ -7283,8 +7614,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AH(0x00); // success CLEAR_CF(); // success return; - } - else if (ah == 0x03) { + } else if (ah == 0x03) { // Write Diskette Sectors //----------------------------------- @@ -7301,7 +7631,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n if ( base_address < base_es ) { // in case of carry, adjust page by 1 page++; - } + } base_count = (num_sectors * 512) - 1; // check for 64K boundary overrun @@ -7312,7 +7642,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } + } BX_DEBUG_INT13_FL("masking DMA-1 c2\n"); outb(0x000a, 0x06); @@ -7338,30 +7668,9 @@ BX_INFO("floppy: drive>1 || head>1 ...\n //-------------------------------------- // set up floppy controller for transfer //-------------------------------------- - - // 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 @@ BX_INFO("floppy: drive>1 || head>1 ...\n outb(0x03f5, 0); // Gap length outb(0x03f5, 0xff); // Gap length - // turn on interrupts + // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 - val8 = (read_byte(0x0000, 0x043e) & 0x80); - while ( val8 == 0 ) { - val8 = (read_byte(0x0000, 0x043e) & 0x80); + do { + val8 = read_byte(0x0040, 0x0040); + if (val8 == 0) { + floppy_reset_controller(); + SET_AH(0x80); // drive not ready (timeout) + set_diskette_ret_status(0x80); + SET_AL(0); // no sectors written + SET_CF(); // error occurred + return; } - - val8 = 0; // separate asm from while() loop - // turn off interrupts + val8 = (read_byte(0x0040, 0x003e) & 0x80); + } while ( val8 == 0 ); + + val8 = 0; // separate asm from while() loop + // turn off interrupts ASM_START cli ASM_END // set 40:3e bit 7 to 0 - val8 = read_byte(0x0000, 0x043e); + val8 = read_byte(0x0040, 0x003e); val8 &= 0x7f; - write_byte(0x0000, 0x043e, val8); + write_byte(0x0040, 0x003e, val8); // check port 3f4 for accessibility to status bytes val8 = inb(0x3f4); @@ -7436,8 +7753,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n SET_AH(0x00); // success CLEAR_CF(); // success return; - } - else { // if (ah == 0x04) + } else { // if (ah == 0x04) // Verify Diskette Sectors // ??? should track be new val from return_status[3] ? @@ -7446,8 +7762,8 @@ BX_INFO("floppy: drive>1 || head>1 ...\n CLEAR_CF(); // success SET_AH(0x00); // success return; - } - + } + break; case 0x05: // format diskette track BX_DEBUG_INT13_FL("floppy f05\n"); @@ -7462,7 +7778,7 @@ BX_DEBUG_INT13_FL("floppy f05\n"); SET_AH(1); set_diskette_ret_status(1); SET_CF(); // error occurred - } + } // see if drive exists if (floppy_drive_exists(drive) == 0) { @@ -7470,7 +7786,7 @@ BX_DEBUG_INT13_FL("floppy f05\n"); set_diskette_ret_status(0x80); SET_CF(); // error occurred return; - } + } // see if media in drive, and type is known if (floppy_media_known(drive) == 0) { @@ -7480,8 +7796,8 @@ BX_DEBUG_INT13_FL("floppy f05\n"); SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } } + } // set up DMA controller for transfer page = (ES >> 12); // upper 4 bits @@ -7491,7 +7807,7 @@ BX_DEBUG_INT13_FL("floppy f05\n"); if ( base_address < base_es ) { // in case of carry, adjust page by 1 page++; - } + } base_count = (num_sectors * 4) - 1; // check for 64K boundary overrun @@ -7502,7 +7818,7 @@ BX_DEBUG_INT13_FL("floppy f05\n"); SET_AL(0); // no sectors read SET_CF(); // error occurred return; - } + } outb(0x000a, 0x06); outb(0x000c, 0x00); // clear flip-flop @@ -7519,27 +7835,9 @@ BX_DEBUG_INT13_FL("floppy f05\n"); outb(0x000a, 0x02); // set up floppy controller for transfer - val8 = read_byte(0x0000, 0x043e); - val8 &= 0x7f; - write_byte(0x0000, 0x043e, val8); - // turn on motor of selected drive, DMA & int enabled, normal operation - if (drive) - dor = 0x20; - else - dor = 0x10; - dor |= 0x0c; - dor |= drive; - outb(0x03f2, dor); - - // 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 @@ BX_DEBUG_INT13_FL("floppy f05\n"); ASM_START sti ASM_END + // wait on 40:3e bit 7 to become 1 - val8 = (read_byte(0x0000, 0x043e) & 0x80); - while ( val8 == 0 ) { - val8 = (read_byte(0x0000, 0x043e) & 0x80); + do { + val8 = read_byte(0x0040, 0x0040); + if (val8 == 0) { + floppy_reset_controller(); + SET_AH(0x80); // drive not ready (timeout) + set_diskette_ret_status(0x80); + SET_CF(); // error occurred + return; } - val8 = 0; // separate asm from while() loop - // turn off interrupts + val8 = (read_byte(0x0040, 0x003e) & 0x80); + } while ( val8 == 0 ); + + val8 = 0; // separate asm from while() loop + // turn off interrupts ASM_START cli ASM_END // set 40:3e bit 7 to 0 - val8 = read_byte(0x0000, 0x043e); + val8 = read_byte(0x0040, 0x003e); val8 &= 0x7f; - write_byte(0x0000, 0x043e, val8); + write_byte(0x0040, 0x003e, val8); // check port 3f4 for accessibility to status bytes val8 = inb(0x3f4); if ( (val8 & 0xc0) != 0xc0 ) @@ -7915,8 +8222,9 @@ Bit16u seq_nr; Bit16u bootseg; Bit16u bootip; Bit16u status; - - 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 @@ Bit16u seq_nr; // CMOS reg 0x38 & 0xf0 : 3rd boot device // boot device codes: // 0x00 : not defined - // 0x01 : first floppy + // 0x01 : first floppy // 0x02 : first harddrive // 0x03 : first cdrom // 0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot) @@ -7942,16 +8250,25 @@ Bit16u seq_nr; bootdev |= ((inb_cmos(0x38) & 0xf0) << 4); bootdev >>= 4 * seq_nr; bootdev &= 0xf; - if (bootdev == 0) BX_PANIC("No bootable device.\n"); - + + /* Read user selected device */ + bootfirst = read_word(ebda_seg, IPL_BOOTFIRST_OFFSET); + if (bootfirst != 0xFFFF) { + bootdev = bootfirst; + /* User selected device not set */ + write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF); + /* Reset boot sequence */ + write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xFFFF); + } else if (bootdev == 0) BX_PANIC("No bootable device.\n"); + /* Translate from CMOS runes to an IPL table offset by subtracting 1 */ bootdev -= 1; -#else +#else if (seq_nr ==2) BX_PANIC("No more boot devices."); - if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1)) + if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1)) /* Boot from floppy if the bit is set or it's the second boot */ bootdev = 0x00; - else + else bootdev = 0x01; #endif @@ -7963,13 +8280,13 @@ Bit16u seq_nr; /* Do the loading, and set up vector as a far pointer to the boot * address, and bootdrv as the boot drive */ - print_boot_device(e.type); + print_boot_device(&e); switch(e.type) { - case 0x01: /* FDD */ - case 0x02: /* HDD */ - - 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 @@ ASM_START mov dl, _int18_function.bootdrv + 2[bp] mov ax, _int18_function.bootseg + 2[bp] mov es, ax ;; segment - mov bx, #0x0000 ;; offset + xor bx, bx ;; offset mov ah, #0x02 ;; function 2, read diskette sector mov al, #0x01 ;; read 1 sector mov ch, #0x00 ;; track 0 @@ -8002,7 +8319,7 @@ int19_load_done: pop ax pop bp ASM_END - + if (status != 0) { print_boot_failure(e.type, 1); return; @@ -8010,7 +8327,7 @@ ASM_END /* Always check the signature on a HDD boot sector; on FDD, only do * the check if the CMOS doesn't tell us to skip it */ - if (e.type != 0x00 || !((inb_cmos(0x38) & 0x01))) { + if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) { if (read_word(bootseg,0x1fe) != 0xaa55) { print_boot_failure(e.type, 0); return; @@ -8028,7 +8345,7 @@ ASM_END break; #if BX_ELTORITO_BOOT - case 0x03: /* CD-ROM */ + case IPL_TYPE_CDROM: /* CD-ROM */ status = cdrom_boot(); // If failure @@ -8047,7 +8364,7 @@ ASM_END break; #endif - case 0x80: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */ + case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */ bootseg = e.vector >> 16; bootip = e.vector & 0xffff; break; @@ -8055,16 +8372,20 @@ ASM_END default: return; } - + /* Debugging info */ + BX_INFO("Booting from %x:%x\n", bootseg, bootip); + /* Jump to the boot vector */ ASM_START mov bp, sp +// push cs +// push #int18_handler ;; Build an iret stack frame that will take us to the boot vector. ;; iret pops ip, then cs, then flags, so push them in the opposite order. pushf - mov ax, _int18_function.bootseg + 0[bp] + mov ax, _int18_function.bootseg + 0[bp] push ax - mov ax, _int18_function.bootip + 0[bp] + mov ax, _int18_function.bootip + 0[bp] push ax ;; Set the magic number in ax and the boot drive in dl. mov ax, #0xaa55 @@ -8267,7 +8588,11 @@ int1a_function(regs, ds, iret_addr) } else if (regs.u.r8.bl == 0x83) { BX_INFO("bad PCI vendor ID %04x\n", regs.u.r16.dx); } else if (regs.u.r8.bl == 0x86) { - BX_INFO("PCI device %04x:%04x not found\n", regs.u.r16.dx, regs.u.r16.cx); + if (regs.u.r8.al == 0x02) { + BX_INFO("PCI device %04x:%04x not found at index %d\n", regs.u.r16.dx, regs.u.r16.cx, regs.u.r16.si); + } else { + BX_INFO("no PCI device with class code 0x%02x%04x found at index %d\n", regs.u.r8.cl, regs.u.r16.dx, regs.u.r16.si); + } } regs.u.r8.ah = regs.u.r8.bl; SetCF(iret_addr.flags); @@ -8313,11 +8638,11 @@ ASM_END // Done waiting. Bit16u segment, offset; - offset = read_word( 0x40, 0x98 ); - segment = read_word( 0x40, 0x9A ); + segment = read_word( 0x40, 0x98 ); + offset = read_word( 0x40, 0x9A ); write_byte( 0x40, 0xA0, 0 ); // Turn of status byte. outb_cmos( 0xB, registerB & 0x37 ); // Clear the Periodic Interrupt. - write_byte( segment, offset, 0x80 ); // Write to specified flag byte. + write_byte(segment, offset, read_byte(segment, offset) | 0x80 ); // Write to specified flag byte. } else { // Continue waiting. time -= 0x3D1; @@ -8525,13 +8850,18 @@ int13_notcdrom: #endif int13_disk: + ;; int13_harddisk modifies high word of EAX + shr eax, #16 + push ax call _int13_harddisk + pop ax + shl eax, #16 int13_out: pop ds pop es popa - iret + iret ;---------- ;- INT18h - @@ -8544,19 +8874,19 @@ int18_handler: ;; Boot Failure recovery: xor ax, ax mov ss, ax - ;; Get the boot sequence number out of the IPL memory ;; The first time we do this it will have been set to -1 so ;; we will start from device 0. mov ds, ax - mov bx, word ptr [EBDA_SEG_PTR] + mov bx, word ptr [0x40E] ;; EBDA segment mov ds, bx ;; Set segment mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number inc bx ;; ++ mov IPL_SEQUENCE_OFFSET, bx ;; Write it back - mov ds, ax ;; and reset the segment to zero. + mov ds, ax ;; and reset the segment to zero. ;; Call the C code for the next boot device push bx + call _int18_function ;; Boot failed: invoke the boot recovery function... @@ -8566,6 +8896,7 @@ int18_handler: ;; Boot Failure recovery: ;- INT19h - ;---------- int19_relocated: ;; Boot function, relocated + ;; ;; *** Warning: INT 19h resets the whole machine *** ;; @@ -8577,10 +8908,12 @@ int19_relocated: ;; Boot function, reloc ;; boot sequence will start, which is more or less the required behaviour. ;; ;; Reset SP and SS + mov ax, #0xfffe mov sp, ax xor ax, ax mov ss, ax + call _machine_reset ;---------- @@ -8594,7 +8927,7 @@ int1c_handler: ;; User Timer Tick ;- POST: Floppy Drive - ;---------------------- floppy_drive_post: - mov ax, #0x0000 + xor ax, ax mov ds, ax mov al, #0x00 @@ -8676,7 +9009,7 @@ hard_drive_post: mov dx, #0x03f6 out dx, al - mov ax, #0x0000 + xor ax, ax mov ds, ax mov 0x0474, al /* hard disk status of last operation */ mov 0x0477, al /* hard disk port offset (XT only ???) */ @@ -8691,8 +9024,8 @@ hard_drive_post: SET_INT_VECTOR(0x76, #0xF000, #int76_handler) ;; INT 41h: hard disk 0 configuration pointer ;; INT 46h: hard disk 1 configuration pointer - SET_INT_VECTOR(0x41, word ptr [EBDA_SEG_PTR], #0x003D) - SET_INT_VECTOR(0x46, word ptr [EBDA_SEG_PTR], #0x004D) + SET_INT_VECTOR(0x41, word ptr [0x40E], #0x003D) /* EBDA:003D */ + SET_INT_VECTOR(0x46, word ptr [0x40E], #0x004D) /* EBDA:004D */ ;; move disk geometry data from CMOS to EBDA disk parameter table(s) mov al, #0x12 @@ -8723,7 +9056,7 @@ post_d0_type47: xor ax, ax mov ds, ax - mov ax, word ptr [EBDA_SEG_PTR] + mov ax, word ptr [0x40E] ;; EBDA segment mov ds, ax ;;; Filling EBDA table for hard disk 0. @@ -8869,7 +9202,9 @@ post_d1_type47: ;; 0x2b landing zone high D ;; 0x2c sectors/track E ;;; Fill EBDA table for hard disk 1. - mov ax, #EBDA_SEG + xor ax, ax + mov ds, ax + mov ax, word ptr [0x40E] ;; EBDA segment mov ds, ax mov al, #0x28 out #0x70, al @@ -8992,7 +9327,7 @@ ebda_post: #endif xor ax, ax ; mov EBDA seg into 40E mov ds, ax - mov word ptr [EBDA_SEG_PTR], #EBDA_SEG + mov word ptr [0x40E], #EBDA_SEG ret;; ;-------------------- @@ -9000,13 +9335,42 @@ ebda_post: ;-------------------- ; relocated here because the primary POST area isnt big enough. eoi_jmp_post: - call eoi_both_pics - + mov al, #0x20 + out #0xA0, al ;; slave PIC EOI + mov al, #0x20 + out #0x20, al ;; master PIC EOI + +jmp_post_0x467: xor ax, ax mov ds, ax jmp far ptr [0x467] +iret_post_0x467: + xor ax, ax + mov ds, ax + + mov sp, [0x467] + mov ss, [0x469] + iret + +retf_post_0x467: + xor ax, ax + mov ds, ax + + mov sp, [0x467] + mov ss, [0x469] + retf + +s3_post: +#if BX_ROMBIOS32 + call rombios32_init +#endif + call _s3_resume + mov bl, #0x00 + and ax, ax + jz normal_post + call _s3_resume_panic ;-------------------- eoi_both_pics: @@ -9159,16 +9523,22 @@ bios32_structure: .align 16 bios32_entry_point: - pushf - cmp eax, #0x49435024 + pushfd + cmp eax, #0x49435024 ;; "$PCI" jne unknown_service mov eax, #0x80000000 mov dx, #0x0cf8 out dx, eax mov dx, #0x0cfc in eax, dx - cmp eax, #0x12378086 +#ifdef PCI_FIXED_HOST_BRIDGE + cmp eax, #PCI_FIXED_HOST_BRIDGE jne unknown_service +#else + ;; say ok if a device is present + cmp eax, #0xffffffff + je unknown_service +#endif mov ebx, #0x000f0000 mov ecx, #0 mov edx, #pcibios_protected @@ -9177,12 +9547,15 @@ unknown_service: unknown_service: mov al, #0x80 bios32_end: - popf +#ifdef BX_QEMU + and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu +#endif + popfd retf .align 16 pcibios_protected: - pushf + pushfd cli push esi push edi @@ -9190,15 +9563,15 @@ pcibios_protected: jne pci_pro_f02 mov bx, #0x0210 mov cx, #0 - mov edx, #0x20494350 + mov edx, #0x20494350 ;; "PCI " mov al, #0x01 jmp pci_pro_ok pci_pro_f02: ;; find pci device cmp al, #0x02 - jne pci_pro_f08 + jne pci_pro_f03 shl ecx, #16 mov cx, dx - mov bx, #0x0000 + xor bx, bx mov di, #0x00 pci_pro_devloop: call pci_pro_select_reg @@ -9213,6 +9586,27 @@ pci_pro_nextdev: inc bx cmp bx, #0x0100 jne pci_pro_devloop + mov ah, #0x86 + jmp pci_pro_fail +pci_pro_f03: ;; find class code + cmp al, #0x03 + jne pci_pro_f08 + xor bx, bx + mov di, #0x08 +pci_pro_devloop2: + call pci_pro_select_reg + mov dx, #0x0cfc + in eax, dx + shr eax, #8 + cmp eax, ecx + jne pci_pro_nextdev2 + cmp si, #0 + je pci_pro_ok + dec si +pci_pro_nextdev2: + inc bx + cmp bx, #0x0100 + jne pci_pro_devloop2 mov ah, #0x86 jmp pci_pro_fail pci_pro_f08: ;; read configuration byte @@ -9288,16 +9682,20 @@ pci_pro_fail: pci_pro_fail: pop edi pop esi - sti - popf +#ifdef BX_QEMU + and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu +#endif + popfd stc retf pci_pro_ok: xor ah, ah pop edi pop esi - sti - popf +#ifdef BX_QEMU + and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu +#endif + popfd clc retf @@ -9324,8 +9722,14 @@ pcibios_real: out dx, eax mov dx, #0x0cfc in eax, dx - cmp eax, #0x12378086 +#ifdef PCI_FIXED_HOST_BRIDGE + cmp eax, #PCI_FIXED_HOST_BRIDGE je pci_present +#else + ;; say ok if a device is present + cmp eax, #0xffffffff + jne pci_present +#endif pop dx pop eax mov ah, #0xff @@ -9339,7 +9743,7 @@ pci_present: mov ax, #0x0001 mov bx, #0x0210 mov cx, #0 - mov edx, #0x20494350 + mov edx, #0x20494350 ;; "PCI " mov edi, #0xf0000 mov di, #pcibios_protected clc @@ -9348,10 +9752,10 @@ pci_real_f02: ;; find pci device push esi push edi cmp al, #0x02 - jne pci_real_f08 + jne pci_real_f03 shl ecx, #16 mov cx, dx - mov bx, #0x0000 + xor bx, bx mov di, #0x00 pci_real_devloop: call pci_real_select_reg @@ -9368,7 +9772,30 @@ pci_real_nextdev: jne pci_real_devloop mov dx, cx shr ecx, #16 - mov ah, #0x86 + mov ax, #0x8602 + jmp pci_real_fail +pci_real_f03: ;; find class code + cmp al, #0x03 + jne pci_real_f08 + xor bx, bx + mov di, #0x08 +pci_real_devloop2: + call pci_real_select_reg + mov dx, #0x0cfc + in eax, dx + shr eax, #8 + cmp eax, ecx + jne pci_real_nextdev2 + cmp si, #0 + je pci_real_ok + dec si +pci_real_nextdev2: + inc bx + cmp bx, #0x0100 + jne pci_real_devloop2 + mov dx, cx + shr ecx, #16 + mov ax, #0x8603 jmp pci_real_fail pci_real_f08: ;; read configuration byte cmp al, #0x08 @@ -9430,7 +9857,7 @@ pci_real_f0c: ;; write configuration wor jmp pci_real_ok pci_real_f0d: ;; write configuration dword cmp al, #0x0d - jne pci_real_unknown + jne pci_real_f0e call pci_real_select_reg push dx mov dx, #0x0cfc @@ -9438,6 +9865,46 @@ pci_real_f0d: ;; write configuration dwo out dx, eax pop dx jmp pci_real_ok +pci_real_f0e: ;; get irq routing options + cmp al, #0x0e + jne pci_real_unknown + SEG ES + cmp word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start + jb pci_real_too_small + SEG ES + mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start + pushf + push ds + push es + push cx + push si + push di + cld + mov si, #pci_routing_table_structure_start + push cs + pop ds + SEG ES + mov cx, [di+2] + SEG ES + mov es, [di+4] + mov di, cx + mov cx, #pci_routing_table_structure_end - pci_routing_table_structure_start + rep + movsb + pop di + pop si + pop cx + pop es + pop ds + popf + mov bx, #(1 << 9) | (1 << 11) ;; irq 9 and 11 are used + jmp pci_real_ok +pci_real_too_small: + SEG ES + mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start + mov ah, #0x89 + jmp pci_real_fail + pci_real_unknown: mov ah, #0x81 pci_real_fail: @@ -9464,7 +9931,7 @@ pci_real_select_reg: out dx, eax pop dx ret - + .align 16 pci_routing_table_structure: db 0x24, 0x50, 0x49, 0x52 ;; "$PIR" signature @@ -9472,21 +9939,22 @@ pci_routing_table_structure: dw 32 + (6 * 16) ;; table size db 0 ;; PCI interrupt router bus db 0x08 ;; PCI interrupt router DevFunc - dw 0x0000 ;; PCI exclusive IRQs + dw 0x0000 ;; PCI exclusive IRQs dw 0x8086 ;; compatible PCI interrupt router vendor ID - dw 0x7000 ;; compatible PCI interrupt router device ID + dw 0x122e ;; compatible PCI interrupt router device ID dw 0,0 ;; Miniport data db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved - db 0x07 ;; checksum + db 0x37 ;; checksum +pci_routing_table_structure_start: ;; first slot entry PCI-to-ISA (embedded) db 0 ;; pci bus number db 0x08 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA#: pointer into PCI2ISA config space - dw 0x0c20 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# - dw 0x0c20 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# - dw 0x0c20 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# dw 0x0c20 ;; IRQ bitmap INTD# db 0 ;; physical slot (0 = embedded) @@ -9495,11 +9963,11 @@ pci_routing_table_structure: db 0 ;; pci bus number db 0x10 ;; pci device number (bit 7-3) db 0x62 ;; link value INTA# - dw 0x0c20 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x63 ;; link value INTB# - dw 0x0c20 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x60 ;; link value INTC# - dw 0x0c20 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x61 ;; link value INTD# dw 0x0c20 ;; IRQ bitmap INTD# db 1 ;; physical slot (0 = embedded) @@ -9508,11 +9976,11 @@ pci_routing_table_structure: db 0 ;; pci bus number db 0x18 ;; pci device number (bit 7-3) db 0x63 ;; link value INTA# - dw 0x0c20 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x60 ;; link value INTB# - dw 0x0c20 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x61 ;; link value INTC# - dw 0x0c20 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x62 ;; link value INTD# dw 0x0c20 ;; IRQ bitmap INTD# db 2 ;; physical slot (0 = embedded) @@ -9521,11 +9989,11 @@ pci_routing_table_structure: db 0 ;; pci bus number db 0x20 ;; pci device number (bit 7-3) db 0x60 ;; link value INTA# - dw 0x0c20 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x61 ;; link value INTB# - dw 0x0c20 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x62 ;; link value INTC# - dw 0x0c20 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x63 ;; link value INTD# dw 0x0c20 ;; IRQ bitmap INTD# db 3 ;; physical slot (0 = embedded) @@ -9534,11 +10002,11 @@ pci_routing_table_structure: db 0 ;; pci bus number db 0x28 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA# - dw 0x0c20 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# - dw 0x0c20 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# - dw 0x0c20 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# dw 0x0c20 ;; IRQ bitmap INTD# db 4 ;; physical slot (0 = embedded) @@ -9547,16 +10015,351 @@ pci_routing_table_structure: db 0 ;; pci bus number db 0x30 ;; pci device number (bit 7-3) db 0x62 ;; link value INTA# - dw 0x0c20 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x63 ;; link value INTB# - dw 0x0c20 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x60 ;; link value INTC# - dw 0x0c20 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x61 ;; link value INTD# dw 0x0c20 ;; IRQ bitmap INTD# db 5 ;; physical slot (0 = embedded) db 0 ;; reserved +pci_routing_table_structure_end: + +#if !BX_ROMBIOS32 +pci_irq_list: + db 11, 10, 9, 5; + +pcibios_init_sel_reg: + push eax + mov eax, #0x800000 + mov ax, bx + shl eax, #8 + and dl, #0xfc + or al, dl + mov dx, #0x0cf8 + out dx, eax + pop eax + ret + +pcibios_init_iomem_bases: + push bp + mov bp, sp + mov eax, #0xe0000000 ;; base for memory init + push eax + mov ax, #0xc000 ;; base for i/o init + push ax + mov ax, #0x0010 ;; start at base address #0 + push ax + mov bx, #0x0008 +pci_init_io_loop1: + mov dl, #0x00 + call pcibios_init_sel_reg + mov dx, #0x0cfc + in ax, dx + cmp ax, #0xffff + jz next_pci_dev + mov dl, #0x04 ;; disable i/o and memory space access + call pcibios_init_sel_reg + mov dx, #0x0cfc + in al, dx + and al, #0xfc + out dx, al +pci_init_io_loop2: + mov dl, [bp-8] + call pcibios_init_sel_reg + mov dx, #0x0cfc + in eax, dx + test al, #0x01 + jnz init_io_base + mov ecx, eax + mov eax, #0xffffffff + out dx, eax + in eax, dx + cmp eax, ecx + je next_pci_base + xor eax, #0xffffffff + mov ecx, eax + mov eax, [bp-4] + out dx, eax + add eax, ecx ;; calculate next free mem base + add eax, #0x01000000 + and eax, #0xff000000 + mov [bp-4], eax + jmp next_pci_base +init_io_base: + mov cx, ax + mov ax, #0xffff + out dx, ax + in ax, dx + cmp ax, cx + je next_pci_base + xor ax, #0xfffe + mov cx, ax + mov ax, [bp-6] + out dx, ax + add ax, cx ;; calculate next free i/o base + add ax, #0x0100 + and ax, #0xff00 + mov [bp-6], ax +next_pci_base: + mov al, [bp-8] + add al, #0x04 + cmp al, #0x28 + je enable_iomem_space + mov byte ptr[bp-8], al + jmp pci_init_io_loop2 +enable_iomem_space: + mov dl, #0x04 ;; enable i/o and memory space access if available + call pcibios_init_sel_reg + mov dx, #0x0cfc + in al, dx + or al, #0x07 + out dx, al +next_pci_dev: + mov byte ptr[bp-8], #0x10 + inc bx + cmp bx, #0x0100 + jne pci_init_io_loop1 + mov sp, bp + pop bp + ret + +pcibios_init_set_elcr: + push ax + push cx + mov dx, #0x04d0 + test al, #0x08 + jz is_master_pic + inc dx + and al, #0x07 +is_master_pic: + mov cl, al + mov bl, #0x01 + shl bl, cl + in al, dx + or al, bl + out dx, al + pop cx + pop ax + ret + +pcibios_init_irqs: + push ds + push bp + mov ax, #0xf000 + mov ds, ax + mov dx, #0x04d0 ;; reset ELCR1 + ELCR2 + mov al, #0x00 + out dx, al + inc dx + out dx, al + mov si, #pci_routing_table_structure + mov bh, [si+8] + mov bl, [si+9] + mov dl, #0x00 + call pcibios_init_sel_reg + mov dx, #0x0cfc + in eax, dx + cmp eax, [si+12] ;; check irq router + jne pci_init_end + mov dl, [si+34] + call pcibios_init_sel_reg + push bx ;; save irq router bus + devfunc + mov dx, #0x0cfc + mov ax, #0x8080 + out dx, ax ;; reset PIRQ route control + add dx, #2 + out dx, ax + mov ax, [si+6] + sub ax, #0x20 + shr ax, #4 + mov cx, ax + add si, #0x20 ;; set pointer to 1st entry + mov bp, sp + mov ax, #pci_irq_list + push ax + xor ax, ax + push ax +pci_init_irq_loop1: + mov bh, [si] + mov bl, [si+1] +pci_init_irq_loop2: + mov dl, #0x00 + call pcibios_init_sel_reg + mov dx, #0x0cfc + in ax, dx + cmp ax, #0xffff + jnz pci_test_int_pin + test bl, #0x07 + jz next_pir_entry + jmp next_pci_func +pci_test_int_pin: + mov dl, #0x3c + call pcibios_init_sel_reg + mov dx, #0x0cfd + in al, dx + and al, #0x07 + jz next_pci_func + dec al ;; determine pirq reg + mov dl, #0x03 + mul al, dl + add al, #0x02 + xor ah, ah + mov bx, ax + mov al, [si+bx] + mov dl, al + mov bx, [bp] + call pcibios_init_sel_reg + mov dx, #0x0cfc + and al, #0x03 + add dl, al + in al, dx + cmp al, #0x80 + jb pirq_found + mov bx, [bp-2] ;; pci irq list pointer + mov al, [bx] + out dx, al + inc bx + mov [bp-2], bx + call pcibios_init_set_elcr +pirq_found: + mov bh, [si] + mov bl, [si+1] + add bl, [bp-3] ;; pci function number + mov dl, #0x3c + call pcibios_init_sel_reg + mov dx, #0x0cfc + out dx, al +next_pci_func: + inc byte ptr[bp-3] + inc bl + test bl, #0x07 + jnz pci_init_irq_loop2 +next_pir_entry: + add si, #0x10 + mov byte ptr[bp-3], #0x00 + loop pci_init_irq_loop1 + mov sp, bp + pop bx +pci_init_end: + pop bp + pop ds + ret +#endif // !BX_ROMBIOS32 #endif // BX_PCIBIOS + +#if BX_ROMBIOS32 +rombios32_init: + ;; save a20 and enable it + in al, 0x92 + push ax + or al, #0x02 + out 0x92, al + + ;; save SS:SP to the BDA + xor ax, ax + mov ds, ax + mov 0x0469, ss + mov 0x0467, sp + + SEG CS + lidt [pmode_IDT_info] + SEG CS + lgdt [rombios32_gdt_48] + ;; set PE bit in CR0 + mov eax, cr0 + or al, #0x01 + mov cr0, eax + ;; start protected mode code: ljmpl 0x10:rombios32_init1 + db 0x66, 0xea + dw rombios32_05 + dw 0x000f ;; high 16 bit address + dw 0x0010 + +use32 386 +rombios32_05: + ;; init data segments + mov eax, #0x18 + mov ds, ax + mov es, ax + mov ss, ax + xor eax, eax + mov fs, ax + mov gs, ax + cld + + ;; init the stack pointer to point below EBDA + mov ax, [0x040e] + shl eax, #4 + mov esp, #-0x10 + add esp, eax + + ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32 + push #0x04b0 + push #0x04b2 + + ;; call rombios32 code + mov eax, #0x000e0000 + call eax + + ;; return to 16 bit protected mode first + db 0xea + dd rombios32_10 + dw 0x20 + +use16 386 +rombios32_10: + ;; restore data segment limits to 0xffff + mov ax, #0x28 + mov ds, ax + mov es, ax + mov ss, ax + mov fs, ax + mov gs, ax + + ;; reset PE bit in CR0 + mov eax, cr0 + and al, #0xFE + mov cr0, eax + + ;; far jump to flush CPU queue after transition to real mode + JMP_AP(0xf000, rombios32_real_mode) + +rombios32_real_mode: + ;; restore IDT to normal real-mode defaults + SEG CS + lidt [rmode_IDT_info] + + xor ax, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ;; restore SS:SP from the BDA + mov ss, 0x0469 + xor esp, esp + mov sp, 0x0467 + ;; restore a20 + pop ax + out 0x92, al + ret + +rombios32_gdt_48: + dw 0x30 + dw rombios32_gdt + dw 0x000f + +rombios32_gdt: + dw 0, 0, 0, 0 + dw 0, 0, 0, 0 + dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10) + dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18) + dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff + dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff +#endif // BX_ROMBIOS32 + ; parallel port detection: base address in DX, index in BX, timeout in CL detect_parport: @@ -9628,13 +10431,12 @@ checksum_loop: ret -;; We need a copy of this string, but we are not actually a PnP BIOS, +;; We need a copy of this string, but we are not actually a PnP BIOS, ;; so make sure it is *not* aligned, so OSes will not see it if they scan. .align 16 db 0 pnp_string: .ascii "$PnP" - rom_scan: ;; Scan for existence of valid expansion ROMS. @@ -9652,8 +10454,9 @@ rom_scan: #if BX_TCGBIOS call _tcpa_start_option_rom_scan /* specs: 3.2.3.3 + 10.4.3 */ #endif - mov cx, #0xc000 + rom_scan_loop: + push ax ;; Save AX mov ds, cx mov ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k cmp [0], #0xAA55 ;; look for signature @@ -9670,6 +10473,8 @@ rom_scan_loop: add al, #0x04 block_count_rounded: + xor bx, bx ;; Restore DS back to 0000: + mov ds, bx #if BX_TCGBIOS push ax push ds @@ -9680,7 +10485,7 @@ block_count_rounded: push ecx ;; segment where option rom is located at call _tcpa_option_rom /* specs: 3.2.3.3 */ add sp, #4 ;; pop segment - pop ecx ;; original ecx + pop ecx ;; original ecx pop ds pop ax #endif @@ -9704,11 +10509,11 @@ fetch_bdf: xor ax, ax mov al, [bx] - ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. + ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. ;; That should stop it grabbing INT 19h; we will use its BEV instead. mov bx, #0xf000 mov es, bx - lea di, pnp_string + lea di, pnp_string xor bx, bx ;; Restore DS back to 0000: mov ds, bx @@ -9721,8 +10526,8 @@ fetch_bdf: add sp, #2 ;; Pop offset value pop cx ;; Pop seg value (restore CX) - ;; Look at the ROM's PnP Expansion header. Properly, we're supposed - ;; to init all the ROMs and then go back and build an IPL table of + ;; Look at the ROM's PnP Expansion header. Properly, we're supposed + ;; to init all the ROMs and then go back and build an IPL table of ;; all the bootable devices, but we can get away with one pass. mov ds, cx ;; ROM base mov bx, 0x001a ;; 0x1A is the offset into ROM header that contains... @@ -9730,7 +10535,7 @@ fetch_bdf: cmp ax, #0x5024 ;; we look for signature "$PnP" jne no_bev mov ax, 2[bx] - cmp ax, #0x506e + cmp ax, #0x506e jne no_bev mov ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector @@ -9753,25 +10558,31 @@ fetch_bdf: cli ;; In case expansion ROM BIOS turns IF on add sp, #2 ;; Pop offset value pop cx ;; Pop seg value (restore CX) - jmp no_bev + jmp no_bev no_bcv: mov ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of... cmp ax, #0x0000 ;; the Bootstrap Entry Vector, or zero if there is none. je no_bev - ;; Found a device that thinks it can boot the system. Record its BEV. + ;; Found a device that thinks it can boot the system. Record its BEV and product name string. + mov di, 0x10[bx] ;; Pointer to the product name string or zero if none xor bx, bx mov ds, bx - mov bx, word ptr [EBDA_SEG_PTR] - mov ds, bx ;; Go to the segment where the IPL table lives + mov bx, word ptr [0x40E] ;; EBDA segment + mov ds, bx ;; Go to the segment where the IPL table lives mov bx, IPL_COUNT_OFFSET ;; Read the number of entries so far cmp bx, #IPL_TABLE_ENTRIES je no_bev ;; Get out if the table is full shl bx, #0x4 ;; Turn count into offset (entries are 16 bytes) - mov IPL_TABLE_OFFSET+0[bx], #0x80 ;; This entry is a BEV device - mov IPL_TABLE_OFFSET+6[bx], cx ;; Build a far pointer from the segment... - mov IPL_TABLE_OFFSET+4[bx], ax ;; and the offset + mov IPL_TABLE_OFFSET+0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device + mov IPL_TABLE_OFFSET+6[bx], cx ;; Build a far pointer from the segment... + mov IPL_TABLE_OFFSET+4[bx], ax ;; and the offset + cmp di, #0x0000 + je no_prod_str + mov 0xA[bx], cx ;; Build a far pointer from the segment... + mov 8[bx], di ;; and the offset +no_prod_str: shr bx, #0x4 ;; Turn the offset back into a count inc bx ;; We have one more entry now mov IPL_COUNT_OFFSET, bx ;; Remember that. @@ -9783,7 +10594,8 @@ rom_scan_increment: shl ax, #5 ;; convert 512-bytes blocks to 16-byte increments ;; because the segment selector is shifted left 4 bits. add cx, ax - cmp cx, #0xe000 + pop ax ;; Restore AX + cmp cx, ax jbe rom_scan_loop xor ax, ax ;; Restore DS back to 0000: @@ -9848,234 +10660,7 @@ tcpa_post_part2: #endif -;; for 'C' strings and other data, insert them here with -;; a the following hack: -;; DATA_SEG_DEFS_HERE - - -;-------- -;- POST - -;-------- -.org 0xe05b ; POST Entry Point -post: - - xor ax, ax - - ;; first reset the DMA controllers - out 0x0d,al - out 0xda,al - - ;; then initialize the DMA controllers - mov al, #0xC0 - out 0xD6, al ; cascade mode of channel 4 enabled - mov al, #0x00 - out 0xD4, al ; unmask channel 4 - - ;; Examine CMOS shutdown status. - mov AL, #0x0f - out 0x70, AL - in AL, 0x71 - - ;; backup status - mov bl, al - - ;; Reset CMOS shutdown status. - mov AL, #0x0f - out 0x70, AL ; select CMOS register Fh - mov AL, #0x00 - out 0x71, AL ; set shutdown action to normal - - ;; Examine CMOS shutdown status. - mov al, bl - mov dx, #EBDA_SEG - mov ds, dx - mov [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET], AL - - cli - mov ax, #0xfffe - mov sp, ax - mov ax, #0x0000 - mov ds, ax - mov ss, ax - - ;; zero out BIOS data area (40:00..40:ff) - mov es, ax - mov cx, #0x0080 ;; 128 words - mov di, #0x0400 - cld - rep - stosw - - call _log_bios_start - - ;; set all interrupts to default handler - mov bx, #0x0000 ;; offset index - mov cx, #0x0100 ;; counter (256 interrupts) - mov ax, #dummy_iret_handler - mov dx, #0xF000 - -post_default_ints: - mov [bx], ax - inc bx - inc bx - mov [bx], dx - inc bx - inc bx - loop post_default_ints - - ;; set vector 0x79 to zero - ;; this is used by 'gardian angel' protection system - SET_INT_VECTOR(0x79, #0, #0) - - ;; base memory in K 40:13 (word) - mov ax, #BASE_MEM_IN_K - mov 0x0413, ax - - - ;; Manufacturing Test 40:12 - ;; zerod out above - - ;; Warm Boot Flag 0040:0072 - ;; value of 1234h = skip memory checks - ;; zerod out above - - - ;; Printer Services vector - SET_INT_VECTOR(0x17, #0xF000, #int17_handler) - - ;; Bootstrap failure vector - SET_INT_VECTOR(0x18, #0xF000, #int18_handler) - - ;; Bootstrap Loader vector - SET_INT_VECTOR(0x19, #0xF000, #int19_handler) - - ;; User Timer Tick vector - SET_INT_VECTOR(0x1c, #0xF000, #int1c_handler) - - ;; Memory Size Check vector - SET_INT_VECTOR(0x12, #0xF000, #int12_handler) - - ;; Equipment Configuration Check vector - SET_INT_VECTOR(0x11, #0xF000, #int11_handler) - - ;; System Services - SET_INT_VECTOR(0x15, #0xF000, #int15_handler) - - ;; EBDA setup - call ebda_post - - ;; PIT setup - SET_INT_VECTOR(0x08, #0xF000, #int08_handler) - ;; int 1C already points at dummy_iret_handler (above) - mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 - out 0x43, al -#ifdef HVMASSIST - mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support) - out 0x40, al ; lsb - mov al, #0xe9 - out 0x40, al ; msb -#else - mov al, #0x00 ; maximum count of 0000H = 18.2Hz - out 0x40, al - out 0x40, al -#endif - - ;; Keyboard - SET_INT_VECTOR(0x09, #0xF000, #int09_handler) - SET_INT_VECTOR(0x16, #0xF000, #int16_handler) - - xor ax, ax - mov ds, ax - mov 0x0417, al /* keyboard shift flags, set 1 */ - mov 0x0418, al /* keyboard shift flags, set 2 */ - mov 0x0419, al /* keyboard alt-numpad work area */ - mov 0x0471, al /* keyboard ctrl-break flag */ - mov 0x0497, al /* keyboard status flags 4 */ - mov al, #0x10 - mov 0x0496, al /* keyboard status flags 3 */ - - - /* keyboard head of buffer pointer */ - mov bx, #0x001E - mov 0x041A, bx - - /* keyboard end of buffer pointer */ - mov 0x041C, bx - - /* keyboard pointer to start of buffer */ - mov bx, #0x001E - mov 0x0480, bx - - /* keyboard pointer to end of buffer */ - mov bx, #0x003E - mov 0x0482, bx - - /* init the keyboard */ - call _keyboard_init - - ;; mov CMOS Equipment Byte to BDA Equipment Word - mov ax, 0x0410 - mov al, #0x14 - out 0x70, al - in al, 0x71 - mov 0x0410, ax - -#if BX_TCGBIOS - call tcpa_post_part1 -#endif - - ;; Parallel setup - SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler) - xor ax, ax - mov ds, ax - xor bx, bx - mov cl, #0x14 ; timeout value - mov dx, #0x378 ; Parallel I/O address, port 1 - call detect_parport - mov dx, #0x278 ; Parallel I/O address, port 2 - call detect_parport - shl bx, #0x0e - mov ax, 0x410 ; Equipment word bits 14..15 determing # parallel ports - and ax, #0x3fff - or ax, bx ; set number of parallel ports - mov 0x410, ax - - ;; Serial setup - SET_INT_VECTOR(0x0C, #0xF000, #dummy_iret_handler) - SET_INT_VECTOR(0x14, #0xF000, #int14_handler) - xor bx, bx - mov cl, #0x0a ; timeout value - mov dx, #0x03f8 ; Serial I/O address, port 1 - call detect_serial - mov dx, #0x02f8 ; Serial I/O address, port 2 - call detect_serial - mov dx, #0x03e8 ; Serial I/O address, port 3 - call detect_serial - mov dx, #0x02e8 ; Serial I/O address, port 4 - call detect_serial - shl bx, #0x09 - mov ax, 0x410 ; Equipment word bits 9..11 determing # serial ports - and ax, #0xf1ff - or ax, bx ; set number of serial port - mov 0x410, ax - - ;; CMOS RTC - SET_INT_VECTOR(0x1A, #0xF000, #int1a_handler) - SET_INT_VECTOR(0x4A, #0xF000, #dummy_iret_handler) - SET_INT_VECTOR(0x70, #0xF000, #int70_handler) - ;; BIOS DATA AREA 0x4CE ??? - call timer_tick_post - - ;; PS/2 mouse setup - SET_INT_VECTOR(0x74, #0xF000, #int74_handler) - - ;; IRQ13 (FPU exception) setup - SET_INT_VECTOR(0x75, #0xF000, #int75_handler) - - ;; Video setup - SET_INT_VECTOR(0x10, #0xF000, #int10_handler) - - ;; PIC +post_init_pic: mov al, #0x11 ; send initialisation commands out 0x20, al out 0xa0, al @@ -10098,6 +10683,329 @@ post_default_ints: mov al, #0x9f #endif out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14 + ret + +;; the following area can be used to write dynamically generated tables + .align 16 +bios_table_area_start: + dd 0xaafb4442 + dd bios_table_area_end - bios_table_area_start - 8; + +;-------- +;- POST - +;-------- +.org 0xe05b ; POST Entry Point +post: + + xor ax, ax + + ;; first reset the DMA controllers + out 0x0d,al + out 0xda,al + + ;; then initialize the DMA controllers + mov al, #0xC0 + out 0xD6, al ; cascade mode of channel 4 enabled + mov al, #0x00 + out 0xD4, al ; unmask channel 4 + + ;; Examine CMOS shutdown status. + mov AL, #0x0f + out 0x70, AL + in AL, 0x71 + + ;; backup status + mov bl, al + + ;; Reset CMOS shutdown status. + mov AL, #0x0f + out 0x70, AL ; select CMOS register Fh + mov AL, #0x00 + out 0x71, AL ; set shutdown action to normal + + ;; Examine CMOS shutdown status. + mov al, bl + + ;; 0x00, 0x09, 0x0D+ = normal startup + cmp AL, #0x00 + jz normal_post + cmp AL, #0x0d + jae normal_post + cmp AL, #0x09 + je normal_post + + ;; 0x05 = eoi + jmp via [0x40:0x67] jump + cmp al, #0x05 + je eoi_jmp_post + + ;; 0x0A = jmp via [0x40:0x67] jump + cmp al, #0x0a + je jmp_post_0x467 + + ;; 0x0B = iret via [0x40:0x67] + cmp al, #0x0b + je iret_post_0x467 + + ;; 0x0C = retf via [0x40:0x67] + cmp al, #0x0c + je retf_post_0x467 + + ;; Examine CMOS shutdown status. + ;; 0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status. + push bx + call _shutdown_status_panic + +#if 0 + HALT(__LINE__) + ; + ;#if 0 + ; 0xb0, 0x20, /* mov al, #0x20 */ + ; 0xe6, 0x20, /* out 0x20, al ;send EOI to PIC */ + ;#endif + ; + pop es + pop ds + popa + iret +#endif + +normal_post: + ; case 0: normal startup + + cli + mov ax, #0xfffe + mov sp, ax + xor ax, ax + mov ds, ax + mov ss, ax + + ;; Save shutdown status + mov 0x04b0, bl + + cmp bl, #0xfe + jz s3_post + + ;; zero out BIOS data area (40:00..40:ff) + mov es, ax + mov cx, #0x0080 ;; 128 words + mov di, #0x0400 + cld + rep + stosw + + call _log_bios_start + + ;; set all interrupts to default handler + xor bx, bx ;; offset index + mov cx, #0x0100 ;; counter (256 interrupts) + mov ax, #dummy_iret_handler + mov dx, #0xF000 + +post_default_ints: + mov [bx], ax + add bx, #2 + mov [bx], dx + add bx, #2 + loop post_default_ints + + ;; set vector 0x79 to zero + ;; this is used by 'gardian angel' protection system + SET_INT_VECTOR(0x79, #0, #0) + + ;; base memory in K 40:13 (word) + mov ax, #BASE_MEM_IN_K + mov 0x0413, ax + + + ;; Manufacturing Test 40:12 + ;; zerod out above + + ;; Warm Boot Flag 0040:0072 + ;; value of 1234h = skip memory checks + ;; zerod out above + + + ;; Printer Services vector + SET_INT_VECTOR(0x17, #0xF000, #int17_handler) + + ;; Bootstrap failure vector + SET_INT_VECTOR(0x18, #0xF000, #int18_handler) + + ;; Bootstrap Loader vector + SET_INT_VECTOR(0x19, #0xF000, #int19_handler) + + ;; User Timer Tick vector + SET_INT_VECTOR(0x1c, #0xF000, #int1c_handler) + + ;; Memory Size Check vector + SET_INT_VECTOR(0x12, #0xF000, #int12_handler) + + ;; Equipment Configuration Check vector + SET_INT_VECTOR(0x11, #0xF000, #int11_handler) + + ;; System Services + SET_INT_VECTOR(0x15, #0xF000, #int15_handler) + + ;; EBDA setup + call ebda_post + + ;; PIT setup + SET_INT_VECTOR(0x08, #0xF000, #int08_handler) + ;; int 1C already points at dummy_iret_handler (above) + mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 + out 0x43, al +#ifdef HVMASSIST + mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support) + out 0x40, al ; lsb + mov al, #0xe9 + out 0x40, al ; msb +#else + mov al, #0x00 ; maximum count of 0000H = 18.2Hz + out 0x40, al + out 0x40, al +#endif + + ;; Keyboard + SET_INT_VECTOR(0x09, #0xF000, #int09_handler) + SET_INT_VECTOR(0x16, #0xF000, #int16_handler) + + xor ax, ax + mov ds, ax + mov 0x0417, al /* keyboard shift flags, set 1 */ + mov 0x0418, al /* keyboard shift flags, set 2 */ + mov 0x0419, al /* keyboard alt-numpad work area */ + mov 0x0471, al /* keyboard ctrl-break flag */ + mov 0x0497, al /* keyboard status flags 4 */ + mov al, #0x10 + mov 0x0496, al /* keyboard status flags 3 */ + + + /* keyboard head of buffer pointer */ + mov bx, #0x001E + mov 0x041A, bx + + /* keyboard end of buffer pointer */ + mov 0x041C, bx + + /* keyboard pointer to start of buffer */ + mov bx, #0x001E + mov 0x0480, bx + + /* keyboard pointer to end of buffer */ + mov bx, #0x003E + mov 0x0482, bx + + /* init the keyboard */ + call _keyboard_init + + ;; mov CMOS Equipment Byte to BDA Equipment Word + mov ax, 0x0410 + mov al, #0x14 + out 0x70, al + in al, 0x71 + mov 0x0410, ax + +#if BX_TCGBIOS + call tcpa_post_part1 +#endif + + ;; Parallel setup + SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler) + xor ax, ax + mov ds, ax + xor bx, bx + mov cl, #0x14 ; timeout value + mov dx, #0x378 ; Parallel I/O address, port 1 + call detect_parport + mov dx, #0x278 ; Parallel I/O address, port 2 + call detect_parport + shl bx, #0x0e + mov ax, 0x410 ; Equipment word bits 14..15 determing # parallel ports + and ax, #0x3fff + or ax, bx ; set number of parallel ports + mov 0x410, ax + + ;; Serial setup + SET_INT_VECTOR(0x0C, #0xF000, #dummy_iret_handler) + SET_INT_VECTOR(0x14, #0xF000, #int14_handler) + xor bx, bx + mov cl, #0x0a ; timeout value + mov dx, #0x03f8 ; Serial I/O address, port 1 + call detect_serial + mov dx, #0x02f8 ; Serial I/O address, port 2 + call detect_serial + mov dx, #0x03e8 ; Serial I/O address, port 3 + call detect_serial + mov dx, #0x02e8 ; Serial I/O address, port 4 + call detect_serial + shl bx, #0x09 + mov ax, 0x410 ; Equipment word bits 9..11 determing # serial ports + and ax, #0xf1ff + or ax, bx ; set number of serial port + mov 0x410, ax + + ;; CMOS RTC + SET_INT_VECTOR(0x1A, #0xF000, #int1a_handler) + SET_INT_VECTOR(0x4A, #0xF000, #dummy_iret_handler) + SET_INT_VECTOR(0x70, #0xF000, #int70_handler) + ;; BIOS DATA AREA 0x4CE ??? + call timer_tick_post + + ;; PS/2 mouse setup + SET_INT_VECTOR(0x74, #0xF000, #int74_handler) + + ;; IRQ13 (FPU exception) setup + SET_INT_VECTOR(0x75, #0xF000, #int75_handler) + + ;; Video setup + SET_INT_VECTOR(0x10, #0xF000, #int10_handler) + + ;; PIC + call post_init_pic + + mov cx, #0xc000 ;; init vga bios + mov ax, #0xc780 + call rom_scan + + call _print_bios_banner + +#if BX_ROMBIOS32 + call rombios32_init +#else +#if BX_PCIBIOS + call pcibios_init_iomem_bases + call pcibios_init_irqs +#endif //BX_PCIBIOS +#endif + + ;; + ;; Floppy setup + ;; + call floppy_drive_post + + ;; + ;; Hard Drive setup + ;; + call hard_drive_post + +#if BX_USE_ATADRV + + ;; + ;; ATA/ATAPI driver setup + ;; + call _ata_init + call _ata_detect + ;; + +#endif // BX_USE_ATADRV + +#if BX_ELTORITO_BOOT + ;; + ;; eltorito floppy/harddisk emulation from cd + ;; + call _cdemu_init + ;; +#endif // BX_ELTORITO_BOOT #ifdef HVMASSIST call _enable_rom_write_access @@ -10109,52 +11017,19 @@ post_default_ints: 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 - ;; + 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 @@ nmi: iret int75_handler: - out 0xf0, al // clear irq13 + out 0xf0, al // clear irq13 call eoi_both_pics // clear interrupt int 2 // legacy nmi call iret @@ -10266,7 +11141,7 @@ int14_handler: int14_handler: push ds pusha - mov ax, #0x0000 + xor ax, ax mov ds, ax call _int14_function popa @@ -10371,26 +11246,7 @@ int09_handler: jz int09_finish in al, #0x60 ;;read key from keyboard controller - //test al, #0x80 ;;look for key release - //jnz int09_process_key ;; dont pass releases to intercept? - - ;; check for extended key - cmp al, #0xe0 - jne int09_call_int15_4f - - push ds - xor ax, ax - mov ds, ax - mov al, BYTE [0x496] ;; mf2_state |= 0x01 - or al, #0x01 - mov BYTE [0x496], al - pop ds - - in al, #0x60 ;;read another key from keyboard controller - sti - -int09_call_int15_4f: push ds pusha #ifdef BX_CALL_INT15_4F @@ -10400,8 +11256,27 @@ int09_call_int15_4f: jnc int09_done #endif - -//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 @@ int09_finish: out #0x64, al pop ax iret - - ;---------------------------------------- @@ -10459,7 +11332,7 @@ int0e_loop2: je int0e_loop2 int0e_normal: push ds - mov ax, #0x0000 ;; segment 0000 + xor ax, ax ;; segment 0000 mov ds, ax call eoi_master_pic mov al, 0x043e @@ -10496,7 +11369,7 @@ int17_handler: int17_handler: push ds pusha - mov ax, #0x0000 + xor ax, ax mov ds, ax call _int17_function popa @@ -10686,11 +11559,11 @@ int1a_callfunction: ;; int70_handler: push ds - pusha + pushad xor ax, ax mov ds, ax call _int70_function - popa + popad pop ds iret @@ -10748,7 +11621,7 @@ int08_store_ticks: .org 0xff00 -.ascii "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team." +.ascii BIOS_COPYRIGHT_STRING ;------------------------------------------------ ;- IRET Instruction for Dummy Interrupt Handler - @@ -10770,7 +11643,7 @@ dummy_iret_handler: #ifdef HVMTEST jmp 0xd000:0x0003; #else - jmp 0xf000:post + jmp 0xf000:post #endif .org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY @@ -10783,10 +11656,10 @@ db 0x00 ; filler .org 0xfa6e ;; Character Font for 320x200 & 640x200 Graphics (lower 128 characters) ASM_END /* - * This font comes from the fntcol16.zip package (c) by Joseph Gil + * This font comes from the fntcol16.zip package (c) by Joseph Gil * found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip * This font is public domain - */ + */ static Bit8u vgafont8[128*8]= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -10962,328 +11835,10 @@ db 0,0,0,0,0,0,0 ; 31 bytes db 0,0,0,0,0,0,0 ; 31 bytes ASM_END -#else // !HVMASSIST - +#endif // HVMASSIST ASM_START -.org 0xcc00 +.org 0xcff0 +bios_table_area_end: // bcc-generated data will be placed here - -// For documentation of this config structure, look on developer.intel.com and -// search for multiprocessor specification. Note that when you change anything -// you must update the checksum (a pain!). It would be better to construct this -// with C structures, or at least fill in the checksum automatically. -// -// Maybe this structs could be moved elsewhere than d000 - -#if (BX_SMP_PROCESSORS==1) - // no structure necessary. -#elif (BX_SMP_PROCESSORS==2) -// define the Intel MP Configuration Structure for 2 processors at -// APIC ID 0,1. I/O APIC at ID=2. -.align 16 -mp_config_table: - db 0x50, 0x43, 0x4d, 0x50 ;; "PCMP" signature - dw (mp_config_end-mp_config_table) ;; table length - db 4 ;; spec rev - db 0x65 ;; checksum - .ascii "BOCHSCPU" ;; OEM id = "BOCHSCPU" - db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1 " - db 0x20, 0x20, 0x20, 0x20 - db 0x20, 0x20, 0x20, 0x20 - dw 0,0 ;; oem table ptr - dw 0 ;; oem table size - dw 20 ;; entry count - dw 0x0000, 0xfee0 ;; memory mapped address of local APIC - dw 0 ;; extended table length - db 0 ;; extended table checksum - db 0 ;; reserved -mp_config_proc0: - db 0 ;; entry type=processor - db 0 ;; local APIC id - db 0x11 ;; local APIC version number - db 3 ;; cpu flags: enabled, bootstrap processor - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc1: - db 0 ;; entry type=processor - db 1 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_isa_bus: - db 1 ;; entry type=bus - db 0 ;; bus ID - db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20 ;; bus type="ISA " -mp_config_ioapic: - db 2 ;; entry type=I/O APIC - db 2 ;; apic id=2. linux will set. - db 0x11 ;; I/O APIC version number - db 1 ;; flags=1=enabled - dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC -mp_config_irqs: - db 3 ;; entry type=I/O interrupt - db 0 ;; interrupt type=vectored interrupt - db 0,0 ;; flags po=0, el=0 (linux uses as default) - db 0 ;; source bus ID is ISA - db 0 ;; source bus IRQ - db 2 ;; destination I/O APIC ID - db 0 ;; destination I/O APIC interrrupt in - ;; repeat pattern for interrupts 0-15 - db 3,0,0,0,0,1,2,1 - db 3,0,0,0,0,2,2,2 - db 3,0,0,0,0,3,2,3 - db 3,0,0,0,0,4,2,4 - db 3,0,0,0,0,5,2,5 - db 3,0,0,0,0,6,2,6 - db 3,0,0,0,0,7,2,7 - db 3,0,0,0,0,8,2,8 - db 3,0,0,0,0,9,2,9 - db 3,0,0,0,0,10,2,10 - db 3,0,0,0,0,11,2,11 - db 3,0,0,0,0,12,2,12 - db 3,0,0,0,0,13,2,13 - db 3,0,0,0,0,14,2,14 - db 3,0,0,0,0,15,2,15 -#elif (BX_SMP_PROCESSORS==4) -// define the Intel MP Configuration Structure for 4 processors at -// APIC ID 0,1,2,3. I/O APIC at ID=4. -.align 16 -mp_config_table: - db 0x50, 0x43, 0x4d, 0x50 ;; "PCMP" signature - dw (mp_config_end-mp_config_table) ;; table length - db 4 ;; spec rev - db 0xdd ;; checksum - .ascii "BOCHSCPU" ;; OEM id = "BOCHSCPU" - db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1 " - db 0x20, 0x20, 0x20, 0x20 - db 0x20, 0x20, 0x20, 0x20 - dw 0,0 ;; oem table ptr - dw 0 ;; oem table size - dw 22 ;; entry count - dw 0x0000, 0xfee0 ;; memory mapped address of local APIC - dw 0 ;; extended table length - db 0 ;; extended table checksum - db 0 ;; reserved -mp_config_proc0: - db 0 ;; entry type=processor - db 0 ;; local APIC id - db 0x11 ;; local APIC version number - db 3 ;; cpu flags: enabled, bootstrap processor - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc1: - db 0 ;; entry type=processor - db 1 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc2: - db 0 ;; entry type=processor - db 2 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc3: - db 0 ;; entry type=processor - db 3 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_isa_bus: - db 1 ;; entry type=bus - db 0 ;; bus ID - db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20 ;; bus type="ISA " -mp_config_ioapic: - db 2 ;; entry type=I/O APIC - db 4 ;; apic id=4. linux will set. - db 0x11 ;; I/O APIC version number - db 1 ;; flags=1=enabled - dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC -mp_config_irqs: - db 3 ;; entry type=I/O interrupt - db 0 ;; interrupt type=vectored interrupt - db 0,0 ;; flags po=0, el=0 (linux uses as default) - db 0 ;; source bus ID is ISA - db 0 ;; source bus IRQ - db 4 ;; destination I/O APIC ID - db 0 ;; destination I/O APIC interrrupt in - ;; repeat pattern for interrupts 0-15 - db 3,0,0,0,0,1,4,1 - db 3,0,0,0,0,2,4,2 - db 3,0,0,0,0,3,4,3 - db 3,0,0,0,0,4,4,4 - db 3,0,0,0,0,5,4,5 - db 3,0,0,0,0,6,4,6 - db 3,0,0,0,0,7,4,7 - db 3,0,0,0,0,8,4,8 - db 3,0,0,0,0,9,4,9 - db 3,0,0,0,0,10,4,10 - db 3,0,0,0,0,11,4,11 - db 3,0,0,0,0,12,4,12 - db 3,0,0,0,0,13,4,13 - db 3,0,0,0,0,14,4,14 - db 3,0,0,0,0,15,4,15 -#elif (BX_SMP_PROCESSORS==8) -// define the Intel MP Configuration Structure for 8 processors at -// APIC ID 0,1,2,3,4,5,6,7. I/O APIC at ID=8. -.align 16 -mp_config_table: - db 0x50, 0x43, 0x4d, 0x50 ;; "PCMP" signature - dw (mp_config_end-mp_config_table) ;; table length - db 4 ;; spec rev - db 0xc3 ;; checksum - .ascii "BOCHSCPU" ;; OEM id = "BOCHSCPU" - db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1 " - db 0x20, 0x20, 0x20, 0x20 - db 0x20, 0x20, 0x20, 0x20 - dw 0,0 ;; oem table ptr - dw 0 ;; oem table size - dw 26 ;; entry count - dw 0x0000, 0xfee0 ;; memory mapped address of local APIC - dw 0 ;; extended table length - db 0 ;; extended table checksum - db 0 ;; reserved -mp_config_proc0: - db 0 ;; entry type=processor - db 0 ;; local APIC id - db 0x11 ;; local APIC version number - db 3 ;; cpu flags: enabled, bootstrap processor - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc1: - db 0 ;; entry type=processor - db 1 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc2: - db 0 ;; entry type=processor - db 2 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc3: - db 0 ;; entry type=processor - db 3 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc4: - db 0 ;; entry type=processor - db 4 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc5: - db 0 ;; entry type=processor - db 5 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc6: - db 0 ;; entry type=processor - db 6 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_proc7: - db 0 ;; entry type=processor - db 7 ;; local APIC id - db 0x11 ;; local APIC version number - db 1 ;; cpu flags: enabled - db 0,6,0,0 ;; cpu signature - dw 0x201,0 ;; feature flags - dw 0,0 ;; reserved - dw 0,0 ;; reserved -mp_config_isa_bus: - db 1 ;; entry type=bus - db 0 ;; bus ID - db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20 ;; bus type="ISA " -mp_config_ioapic: - db 2 ;; entry type=I/O APIC - db 8 ;; apic id=8 - db 0x11 ;; I/O APIC version number - db 1 ;; flags=1=enabled - dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC -mp_config_irqs: - db 3 ;; entry type=I/O interrupt - db 0 ;; interrupt type=vectored interrupt - db 0,0 ;; flags po=0, el=0 (linux uses as default) - db 0 ;; source bus ID is ISA - db 0 ;; source bus IRQ - db 8 ;; destination I/O APIC ID - db 0 ;; destination I/O APIC interrrupt in - ;; repeat pattern for interrupts 0-15 - db 3,0,0,0,0,1,8,1 - db 3,0,0,0,0,2,8,2 - db 3,0,0,0,0,3,8,3 - db 3,0,0,0,0,4,8,4 - db 3,0,0,0,0,5,8,5 - db 3,0,0,0,0,6,8,6 - db 3,0,0,0,0,7,8,7 - db 3,0,0,0,0,8,8,8 - db 3,0,0,0,0,9,8,9 - db 3,0,0,0,0,10,8,10 - db 3,0,0,0,0,11,8,11 - db 3,0,0,0,0,12,8,12 - db 3,0,0,0,0,13,8,13 - db 3,0,0,0,0,14,8,14 - db 3,0,0,0,0,15,8,15 -#else -# error Sorry, rombios only has configurations for 1, 2, 4 or 8 processors. -#endif // if (BX_SMP_PROCESSORS==...) - -mp_config_end: // this label used to find length of mp structure - db 0 - -#if (BX_SMP_PROCESSORS>1) -.align 16 -mp_floating_pointer_structure: -db 0x5f, 0x4d, 0x50, 0x5f ; "_MP_" signature -dw mp_config_table, 0xf ;; pointer to MP configuration table -db 1 ;; length of this struct in 16-bit byte chunks -db 4 ;; MP spec revision -db 0xc1 ;; checksum -db 0 ;; MP feature byte 1. value 0 means look at the config table -db 0,0,0,0 ;; MP feature bytes 2-5. -#endif - ASM_END -#endif // HVMASSIST diff -r 768759d4e319 -r 0a393ba0ec0a tools/firmware/rombios/rombios.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/firmware/rombios/rombios.h Thu Dec 18 14:52:53 2008 +0000 @@ -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-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |