Changeset 87784 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- Feb 17, 2021 5:12:35 PM (4 years ago)
- Location:
- trunk/src/VBox/Devices/PC/BIOS
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS/notes.txt
r77117 r87784 43 43 - NetWare 6.x is the only known guest which uses the PCI BIOS service to read 44 44 the IRQ routing table. 45 46 - NetWare 6.5 boot CD is a rare user of INT 15h/86h, asking for 1,000,000 47 microsecond (1 second) delays. The initial NW 6.5 release boots to Caldera 48 DOS and does not exhibit this behavior. NetWare 6.5 SP2 and later boots 49 straight to NetWare and uses the 1-second sleep. 45 50 46 51 - Any disk reads which use bus-master DMA (AHCI, IDE BM) must use VDS -
trunk/src/VBox/Devices/PC/BIOS/system.c
r82968 r87784 285 285 parm [ax] modify nomemory aborts; 286 286 287 /// @todo This method is silly. The RTC should be programmed to fire an interrupt288 // instead of hogging the CPU with inaccurate code.289 void timer_wait(uint32_t usec_wait)290 {291 uint32_t cycles;292 uint8_t old_val;293 uint8_t cur_val;294 295 /* We wait in 15 usec increments. */296 cycles = usec_wait / 15;297 298 old_val = inp(0x61) & 0x10;299 while (cycles--) {300 /* Wait 15us. */301 do {302 cur_val = inp(0x61) & 0x10;303 } while (cur_val != old_val);304 old_val = cur_val;305 }306 }307 308 287 bx_bool set_enable_a20(bx_bool val) 309 288 { … … 427 406 write_word( 0x40, 0x9E, CX ); // High word, delay. 428 407 CLEAR_CF( ); 408 // Unmask IRQ8 so INT70 will get through. 429 409 irqDisable = inb( 0xA1 ); 430 410 outb( 0xA1, irqDisable & 0xFE ); 431 bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through. 432 outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer 411 bRegister = inb_cmos( 0xB ); 412 // Turn on the Periodic Interrupt timer 413 outb_cmos( 0xB, bRegister | 0x40 ); 433 414 } else { 434 415 // Interval already set. 435 416 BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" ); 436 SET_CF(); 437 SET_AH(UNSUPPORTED_FUNCTION); 417 SET_CF(); // AH is left unmodified 438 418 } 439 419 } else if( GET_AL() == 1 ) { … … 454 434 455 435 case 0x86: 456 // Wait for CX:DX microseconds. currently using the 457 // refresh request port 0x61 bit4, toggling every 15usec 458 int_enable(); 459 timer_wait(((uint32_t)CX << 16) | DX); 436 // Set Interval requested. 437 if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) { 438 // Interval not already set. 439 write_byte( 0x40, 0xA0, 1 ); // Set status byte. 440 write_word( 0x40, 0x98, 0x40 ); // Byte location, segment 441 write_word( 0x40, 0x9A, 0xA0 ); // Byte location, offset 442 write_word( 0x40, 0x9C, DX ); // Low word, delay 443 write_word( 0x40, 0x9E, CX ); // High word, delay. 444 // Unmask IRQ8 so INT70 will get through. 445 irqDisable = inb( 0xA1 ); 446 outb( 0xA1, irqDisable & 0xFE ); 447 bRegister = inb_cmos( 0xB ); 448 // Turn on the Periodic Interrupt timer 449 outb_cmos( 0xB, bRegister | 0x40 ); 450 // Now wait until timer interrupt says wait is done. 451 int_enable(); 452 do { 453 halt(); 454 bRegister = read_byte( 0x40, 0xA0 ); 455 } 456 while( !(bRegister & 0x80) ); 457 write_byte( 0x40, 0xA0, 0 ); // Deactivate wait. 458 CLEAR_CF( ); 459 } else { 460 // Interval already set. 461 BX_DEBUG_INT15("int15: Func 86h, failed, already waiting.\n" ); 462 SET_CF(); // AH is left unmodified 463 } 460 464 break; 461 465
Note:
See TracChangeset
for help on using the changeset viewer.