X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fvmboot%2Frombios%2Frombios.c;h=a958848a0fa0a5620fa51ae207caaf6626606d79;hb=f7cc83b3bae64c853f5b7b63e2830b1ea92dfed9;hp=9c0d1f3da1043afe2b4f99836c10596685415190;hpb=624a05de781c51ed5d34a6db2583f884918a9594;p=palacios-OLD.git diff --git a/palacios/src/vmboot/rombios/rombios.c b/palacios/src/vmboot/rombios/rombios.c index 9c0d1f3..a958848 100644 --- a/palacios/src/vmboot/rombios/rombios.c +++ b/palacios/src/vmboot/rombios/rombios.c @@ -1,6 +1,6 @@ // -*- fundamental -*- ///////////////////////////////////////////////////////////////////////// -// $Id: rombios.c,v 1.3 2008/05/02 23:58:51 pdinda Exp $ +// $Id: rombios.c,v 1.12 2008/07/11 22:59:38 pdinda Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. @@ -59,7 +59,7 @@ // $f859 ; INT 15h System Services Entry Point // $fa6e ; Character Font for 320x200 & 640x200 Graphics (lower 128 characters) // $fe6e ; INT 1Ah Time-of-day Service Entry Point -// $fea5 ; INT 08h System Timer ISR Entry Point +/// $fea5 ; INT 08h System Timer ISR Entry Point // $fef3 ; Initial Interrupt Vector Offsets Loaded by POST // $ff53 ; IRET Instruction for Dummy Interrupt Handler // $ff54 ; INT 05h Print Screen Service Entry Point @@ -132,11 +132,11 @@ #define DEBUG_ROMBIOS 1 -#define DEBUG_ATA 1 +#define DEBUG_ATA 0 #define DEBUG_INT13_HD 0 #define DEBUG_INT13_CD 0 #define DEBUG_INT13_ET 0 -#define DEBUG_INT13_FL 1 +#define DEBUG_INT13_FL 0 #define DEBUG_INT15 0 #define DEBUG_INT16 0 #define DEBUG_INT1A 0 @@ -945,10 +945,10 @@ Bit16u cdrom_boot(); #endif // BX_ELTORITO_BOOT -static char bios_cvs_version_string[] = "$Revision: 1.3 $"; -static char bios_date_string[] = "$Date: 2008/05/02 23:58:51 $"; +static char bios_cvs_version_string[] = "$Revision: 1.12 $"; +static char bios_date_string[] = "$Date: 2008/07/11 22:59:38 $"; -static char CVSID[] = "$Id: rombios.c,v 1.3 2008/05/02 23:58:51 pdinda Exp $"; +static char CVSID[] = "$Id: rombios.c,v 1.12 2008/07/11 22:59:38 pdinda Exp $"; /* Offset to skip the CVS $Id: prefix */ #define bios_version_string (CVSID + 4) @@ -1400,12 +1400,13 @@ ASM_END } // Bit16u -//get_DS() -//{ -//ASM_START -// mov ax, ds -//ASM_END -//} +get_DS() +{ +ASM_START + mov ax, ds +ASM_END +} + // // void //set_DS(ds_selector) @@ -1680,9 +1681,11 @@ keyboard_init() while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); /* flush incoming keys */ - max=0x2000; + // temporarily chaged for debug -PAD + // max=0x2000; + max=10; while (--max > 0) { - outb(0x80, 0x00); + outb(0x80, 0x01); if (inb(0x64) & 0x01) { inb(0x60); max = 0x2000; @@ -1700,12 +1703,12 @@ keyboard_init() /* Wait until buffer is empty */ max=0xffff; - while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); + while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x02); if (max==0x0) keyboard_panic(00); /* Wait for data */ max=0xffff; - while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01); + while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x03); if (max==0x0) keyboard_panic(01); /* read self-test result, 0x55 should be returned from 0x60 */ @@ -2846,7 +2849,7 @@ Bit32u length; Bit16u iobase1, iobase2; Bit16u lcount, lbefore, lafter, count; Bit8u channel, slave; - Bit8u status, mode, lmode; + Bit8u status, error, mode, lmode; Bit32u total, transfer; channel = device / 2; @@ -2877,31 +2880,72 @@ Bit32u length; write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); - status = inb(iobase1 + ATA_CB_STAT); - if (status & ATA_CB_STAT_BSY) return 2; +#define STATUS_WAIT_FOR(x) do { status=inb(iobase1+ATA_CB_STAT); } while (!(x)) +#define ALT_STATUS_WAIT_FOR(x) do { status=inb(iobase2+ATA_CB_ASTAT); } while (!(x)) +#define ERROR_UPDATE() do { error=inb(iobase1+ATA_CB_ERR); } while (0) +#define STATUS_UPDATE() do { status=inb(iobase1+ATA_CB_STAT); } while (0) +#define ALT_STATUS_UPDATE() do { status=inb(iobase1+ATA_CB_STAT); } while (0) +#define WAIT_FOR_NOT_BUSY() STATUS_WAIT_FOR((status&ATA_CB_STAT_BSY)==0) +#define WAIT_FOR_DATA_REQUEST() STATUS_WAIT_FOR((status&ATA_CB_STAT_DRQ)) +#define WAIT_FOR_DRIVE_READY() STATUS_WAIT_FOR((status&ATA_CB_STAT_RDY)) +#define WAIT_FOR_NOT_BUSY_AND_DRIVE_READY() STATUS_WAIT_FOR(((status&ATA_CB_STAT_BSY)==0)&&((status&ATA_CB_STAT_RDY))) +#define WAIT_FOR_NOT_BUSY_AND_DATA_REQUEST() STATUS_WAIT_FOR((status&ATA_CB_STAT_BSY)==0)&&((status&ATA_CB_STAT_DRQ))) + + + +retry_on_media_change: + WAIT_FOR_NOT_BUSY(); + + //BX_DEBUG_ATA("ata_cmd_packet: not busy done\n"); + + // We have already selected the appropriate controller (iobase1,2) + // select master or slave + outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); + + STATUS_UPDATE(); + + //BX_DEBUG_ATA("ata_cmd_packet: drive selected (%d) status=0x%x\n", slave,(unsigned)status); + + + // Technically, we should be calling this here + // but QEMU's device model appears to be broken and RDY never is assserted + // on a drive change + // WAIT_FOR_NOT_BUSY_AND_DRIVE_READY(); + WAIT_FOR_NOT_BUSY(); + + //BX_DEBUG_ATA("ata_cmd_packet: not busy\n"); + + // set "noninterruptable" 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); + // no DMA + outb(iobase1 + ATA_CB_FR, 0x00); + // This conveys the maximum bytecount. count&0xff in low, count>>8 in high + // it is not actually doing anything with cylinders 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); + // Not sure about these + outb(iobase1 + ATA_CB_SC, 0x00); + outb(iobase1 + ATA_CB_SN, 0x00); + + //BX_DEBUG_ATA("ata_cmd_packet: configuration done\n"); + + // Issue command for packet 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; - } + //BX_DEBUG_ATA("ata_cmd_packet: A0 issued to drive\n"); + + ALT_STATUS_WAIT_FOR((status&ATA_CB_STAT_BSY)==0); - if (status & ATA_CB_STAT_ERR) { - BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status); - return 3; - } else if ( !(status & ATA_CB_STAT_DRQ) ) { - BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status); - return 4; - } + //BX_DEBUG_ATA("ata_cmd_packet: alt status shows not busy\n"); + + STATUS_UPDATE(); + + //BX_DEBUG_ATA("ata_cmd_packet: main status shows 0x%x\n",(unsigned)status); + + WAIT_FOR_DATA_REQUEST(); + + //BX_DEBUG_ATA("ata_cmd_packet: data request is set\n"); // Normalize address cmdseg += (cmdoff / 16); @@ -2928,61 +2972,109 @@ ASM_START pop bp ASM_END + + ALT_STATUS_WAIT_FOR((status&ATA_CB_STAT_BSY)==0); + + STATUS_UPDATE(); + ERROR_UPDATE(); + + BX_DEBUG_ATA("ata_cmd_packet: after packet: 0x%x error 0x%x\n",(unsigned)status,(unsigned)error); + + if (status&ATA_CB_STAT_ERR && error&ATA_CB_ER_MC) { + BX_DEBUG_ATA("ata_cmd_packet: caught unexpected media change. Retrying\n"); + goto retry_on_media_change; + } + + + if (inout == ATA_DATA_NO) { - status = inb(iobase1 + ATA_CB_STAT); + STATUS_UPDATE(); } else { - while (1) { + + while (1) { + + // This while loop is quite bizarre + // Under both success and failure, you'll go through it once + // and then just a wee bit the second time - PAD + + + ALT_STATUS_WAIT_FOR((status&ATA_CB_STAT_BSY)==0); + + STATUS_UPDATE(); + ERROR_UPDATE(); + + BX_DEBUG_ATA("ata_cmd_packet/dataxferloop: status=0x%x, error=0x%x\n",(unsigned)status,(unsigned)error); + - status = inb(iobase1 + ATA_CB_STAT); + +#if 0 +// +// According to specatapi, the following is how you're supposed +// To tell when there is no more data for you +// But it doesn't work on at least some hardware - PAD + if ((status&ATA_CB_STAT_BSY) && !(status&ATA_CB_STAT_DRQ)) { + // done with data tranfer + // we wait for it to flip + ALT_STATUS_WAIT_FOR((status&ATA_CB_STAT_BSY)==0); + // then read one more time + STATUS_UPDATE(); + // then we are done + break; + } + +#else // Check if command completed if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break; +#endif if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status); return 3; } - + + // If we get here, we are ready and should have DRQ + // and so data is available // 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); + != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { + BX_DEBUG_ATA("ata_cmd_packet 1: not ready (status %02x)\n", status); return 4; - } - + } + // Normalize address bufseg += (bufoff / 16); bufoff %= 16; - + // Get the byte count lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL); - + // adjust to read what we want if(header>lcount) { - lbefore=lcount; - header-=lcount; - lcount=0; - } + lbefore=lcount; + header-=lcount; + lcount=0; + } else { lbefore=header; header=0; lcount-=lbefore; - } - + } + if(lcount>length) { lafter=lcount-length; lcount=length; length=0; - } + } else { lafter=0; length-=lcount; - } - + } + // Save byte count count = lcount; - + BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter); BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff); @@ -3091,19 +3183,21 @@ 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) ) != ATA_CB_STAT_RDY ) { - BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status); - return 4; + BX_DEBUG_ATA("ata_cmd_packet 2 : not ready (status %02x)\n", (unsigned) status); + return 4; } // Enable interrupts outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); return 0; + } // --------------------------------------------------------------------------- // End of ATA/ATAPI Driver // --------------------------------------------------------------------------- + // --------------------------------------------------------------------------- // Start of ATA/ATAPI generic functions // --------------------------------------------------------------------------- @@ -3236,15 +3330,20 @@ cdrom_boot() // if not found if(device >= BX_MAX_ATA_DEVICES) return 2; + + // Read the Boot Record Volume Descriptor memsetb(get_SS(),atacmd,0,12); atacmd[0]=0x28; // READ command + atacmd[1]=0x0 ; // reserved - not sure why this wasn't zeroed to begin with -PAD + atacmd[6]=0x0 ; // reserved - ... -PAD atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors atacmd[8]=(0x01 & 0x00ff); // Sectors atacmd[2]=(0x11 & 0xff000000) >> 24; // LBA atacmd[3]=(0x11 & 0x00ff0000) >> 16; atacmd[4]=(0x11 & 0x0000ff00) >> 8; atacmd[5]=(0x11 & 0x000000ff); + atacmd[9]=atacmd[10]=atacmd[11]=0x0; // just to be safe -PAD if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) return 3; @@ -4112,10 +4211,13 @@ ASM_END case 0x20: // coded by osmaker aka K.J. if(regs.u.r32.edx == 0x534D4150) /* SMAP */ { -#ifdef HVMASSIST +#if defined(HVMASSIST) && 0 if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) { + Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14; + BX_DEBUG_INT15("OK bx=%x\n",regs.u.r16.bx); + if (regs.u.r16.bx + 0x14 <= e820_table_size) { memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + regs.u.r16.bx, 0x14); @@ -6716,16 +6818,15 @@ int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit8u drive_type, num_floppies, ah; Bit16u es, last_addr; - printf("In int13_diskette\n"); - 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); + //printf("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(); switch ( ah ) { case 0x00: // diskette controller reset -BX_DEBUG_INT13_FL("floppy f00\n"); + BX_DEBUG_INT13_FL("floppy f00\n"); drive = GET_ELDL(); if (drive > 1) { SET_AH(1); // invalid param @@ -7638,6 +7739,7 @@ Bit8u bseqnr; if (bootcd != 0) { status = cdrom_boot(); + BX_DEBUG("CDBoot:%x\n",status); // If failure @@ -7645,11 +7747,11 @@ Bit8u bseqnr; print_cdromboot_failure(status); print_boot_failure(bootcd, bootdrv, 1, lastdrive); return 0x00000000; - } - + } + bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment); bootdrv = (Bit8u)(status>>8); - } + } #endif // BX_ELTORITO_BOOT @@ -7717,6 +7819,8 @@ ASM_END print_boot_device(0, bootdrv); #endif // BX_ELTORITO_BOOT + BX_DEBUG("boot to %x\n", (((Bit32u)bootdrv) << 16) + bootseg); + // return the boot segment return (((Bit32u)bootdrv) << 16) + bootseg; } @@ -8244,7 +8348,9 @@ boot_setup: mov [bp], ax ;; set bp to zero mov ax, #0xaa55 ;; set ok flag + pop bp + iret ;; Beam me up Scotty ;---------- @@ -8781,7 +8887,7 @@ int76_handler: mov ds, ax mov 0x008E, #0xff call eoi_both_pics - pop ds + pop ds pop ax iret @@ -9447,6 +9553,7 @@ rom_scan_loop: jne rom_scan_increment call rom_checksum jnz rom_scan_increment + mov al, [2] ;; change increment to ROM length in 512-byte blocks ;; We want our increment in 512-byte quantities, rounded to