Commit 330d0414a5968d36edb635c63a729ffa55520e76
1 parent
3802ce26
keyboard emulation - accepts to boot with Bochs BIOS and LGPL'ed VGA BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@338 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
605 additions
and
92 deletions
vl.c
| ... | ... | @@ -52,10 +52,28 @@ |
| 52 | 52 | |
| 53 | 53 | #define DEBUG_LOGFILE "/tmp/vl.log" |
| 54 | 54 | #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" |
| 55 | +#define BIOS_FILENAME "bios.bin" | |
| 56 | +#define VGABIOS_FILENAME "vgabios.bin" | |
| 55 | 57 | |
| 56 | 58 | //#define DEBUG_UNUSED_IOPORT |
| 59 | + | |
| 57 | 60 | //#define DEBUG_IRQ_LATENCY |
| 58 | 61 | |
| 62 | +/* output Bochs bios info messages */ | |
| 63 | +//#define DEBUG_BIOS | |
| 64 | + | |
| 65 | +/* debug IDE devices */ | |
| 66 | +//#define DEBUG_IDE | |
| 67 | + | |
| 68 | +/* debug PIC */ | |
| 69 | +//#define DEBUG_PIC | |
| 70 | + | |
| 71 | +/* debug NE2000 card */ | |
| 72 | +//#define DEBUG_NE2000 | |
| 73 | + | |
| 74 | +/* debug PC keyboard */ | |
| 75 | +//#define DEBUG_KBD | |
| 76 | + | |
| 59 | 77 | #define PHYS_RAM_BASE 0xac000000 |
| 60 | 78 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
| 61 | 79 | |
| ... | ... | @@ -185,6 +203,7 @@ typedef uint32_t (IOPortReadFunc)(CPUX86State *env, uint32_t address); |
| 185 | 203 | |
| 186 | 204 | #define MAX_IOPORTS 4096 |
| 187 | 205 | |
| 206 | +static const char *interp_prefix = CONFIG_QEMU_PREFIX; | |
| 188 | 207 | char phys_ram_file[1024]; |
| 189 | 208 | CPUX86State *global_env; |
| 190 | 209 | CPUX86State *cpu_single_env; |
| ... | ... | @@ -216,15 +235,15 @@ void default_ioport_writeb(CPUX86State *env, uint32_t address, uint32_t data) |
| 216 | 235 | uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) |
| 217 | 236 | { |
| 218 | 237 | uint32_t data; |
| 219 | - data = ioport_read_table[0][address](env, address); | |
| 220 | - data |= ioport_read_table[0][address + 1](env, address + 1) << 8; | |
| 238 | + data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](env, address); | |
| 239 | + data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1) << 8; | |
| 221 | 240 | return data; |
| 222 | 241 | } |
| 223 | 242 | |
| 224 | 243 | void default_ioport_writew(CPUX86State *env, uint32_t address, uint32_t data) |
| 225 | 244 | { |
| 226 | - ioport_write_table[0][address](env, address, data & 0xff); | |
| 227 | - ioport_write_table[0][address + 1](env, address + 1, (data >> 8) & 0xff); | |
| 245 | + ioport_write_table[0][address & (MAX_IOPORTS - 1)](env, address, data & 0xff); | |
| 246 | + ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1, (data >> 8) & 0xff); | |
| 228 | 247 | } |
| 229 | 248 | |
| 230 | 249 | uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) |
| ... | ... | @@ -516,6 +535,7 @@ void cmos_init(void) |
| 516 | 535 | { |
| 517 | 536 | struct tm *tm; |
| 518 | 537 | time_t ti; |
| 538 | + int val; | |
| 519 | 539 | |
| 520 | 540 | ti = time(NULL); |
| 521 | 541 | tm = gmtime(&ti); |
| ... | ... | @@ -532,8 +552,27 @@ void cmos_init(void) |
| 532 | 552 | cmos_data[RTC_REG_C] = 0x00; |
| 533 | 553 | cmos_data[RTC_REG_D] = 0x80; |
| 534 | 554 | |
| 555 | + /* various important CMOS locations needed by PC/Bochs bios */ | |
| 556 | + | |
| 535 | 557 | cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
| 536 | 558 | |
| 559 | + /* memory size */ | |
| 560 | + val = (phys_ram_size / 1024) - 1024; | |
| 561 | + if (val > 65535) | |
| 562 | + val = 65535; | |
| 563 | + cmos_data[0x17] = val; | |
| 564 | + cmos_data[0x18] = val >> 8; | |
| 565 | + cmos_data[0x30] = val; | |
| 566 | + cmos_data[0x31] = val >> 8; | |
| 567 | + | |
| 568 | + val = (phys_ram_size / 65536) - ((16 * 1024 * 1024) / 65536); | |
| 569 | + if (val > 65535) | |
| 570 | + val = 65535; | |
| 571 | + cmos_data[0x34] = val; | |
| 572 | + cmos_data[0x35] = val >> 8; | |
| 573 | + | |
| 574 | + cmos_data[0x3d] = 0x02; /* hard drive boot */ | |
| 575 | + | |
| 537 | 576 | register_ioport_write(0x70, 2, cmos_ioport_write, 1); |
| 538 | 577 | register_ioport_read(0x70, 2, cmos_ioport_read, 1); |
| 539 | 578 | } |
| ... | ... | @@ -541,8 +580,6 @@ void cmos_init(void) |
| 541 | 580 | /***********************************************************/ |
| 542 | 581 | /* 8259 pic emulation */ |
| 543 | 582 | |
| 544 | -//#define DEBUG_PIC | |
| 545 | - | |
| 546 | 583 | typedef struct PicState { |
| 547 | 584 | uint8_t last_irr; /* edge detection */ |
| 548 | 585 | uint8_t irr; /* interrupt request register */ |
| ... | ... | @@ -1360,8 +1397,6 @@ void serial_init(void) |
| 1360 | 1397 | /***********************************************************/ |
| 1361 | 1398 | /* ne2000 emulation */ |
| 1362 | 1399 | |
| 1363 | -//#define DEBUG_NE2000 | |
| 1364 | - | |
| 1365 | 1400 | #define NE2000_IOPORT 0x300 |
| 1366 | 1401 | #define NE2000_IRQ 9 |
| 1367 | 1402 | |
| ... | ... | @@ -1827,8 +1862,6 @@ void ne2000_init(void) |
| 1827 | 1862 | /***********************************************************/ |
| 1828 | 1863 | /* ide emulation */ |
| 1829 | 1864 | |
| 1830 | -//#define DEBUG_IDE | |
| 1831 | - | |
| 1832 | 1865 | /* Bits of HD_STATUS */ |
| 1833 | 1866 | #define ERR_STAT 0x01 |
| 1834 | 1867 | #define INDEX_STAT 0x02 |
| ... | ... | @@ -2352,16 +2385,50 @@ uint32_t ide_status_read(CPUX86State *env, uint32_t addr) |
| 2352 | 2385 | int ret; |
| 2353 | 2386 | ret = s->status; |
| 2354 | 2387 | #ifdef DEBUG_IDE |
| 2355 | - printf("ide: read addr=0x%x val=%02x\n", addr, ret); | |
| 2388 | + printf("ide: read status val=%02x\n", ret); | |
| 2356 | 2389 | #endif |
| 2357 | 2390 | return ret; |
| 2358 | 2391 | } |
| 2359 | 2392 | |
| 2360 | 2393 | void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2361 | 2394 | { |
| 2362 | - IDEState *s = &ide_state[0]; | |
| 2395 | + IDEState *s; | |
| 2396 | + int i; | |
| 2397 | + | |
| 2398 | +#ifdef DEBUG_IDE | |
| 2399 | + printf("ide: write control val=%02x\n", val); | |
| 2400 | +#endif | |
| 2363 | 2401 | /* common for both drives */ |
| 2364 | - s->cmd = val; | |
| 2402 | + if (!(ide_state[0].cmd & IDE_CMD_RESET) && | |
| 2403 | + (val & IDE_CMD_RESET)) { | |
| 2404 | + /* reset low to high */ | |
| 2405 | + for(i = 0;i < 2; i++) { | |
| 2406 | + s = &ide_state[i]; | |
| 2407 | + s->status = BUSY_STAT | SEEK_STAT; | |
| 2408 | + s->error = 0x01; | |
| 2409 | + } | |
| 2410 | + } else if ((ide_state[0].cmd & IDE_CMD_RESET) && | |
| 2411 | + !(val & IDE_CMD_RESET)) { | |
| 2412 | + /* high to low */ | |
| 2413 | + for(i = 0;i < 2; i++) { | |
| 2414 | + s = &ide_state[i]; | |
| 2415 | + s->status = READY_STAT; | |
| 2416 | + /* set hard disk drive ID */ | |
| 2417 | + s->select &= 0xf0; /* clear head */ | |
| 2418 | + s->nsector = 1; | |
| 2419 | + s->sector = 1; | |
| 2420 | + if (s->nb_sectors == 0) { | |
| 2421 | + /* no disk present */ | |
| 2422 | + s->lcyl = 0x12; | |
| 2423 | + s->hcyl = 0x34; | |
| 2424 | + } else { | |
| 2425 | + s->lcyl = 0; | |
| 2426 | + s->hcyl = 0; | |
| 2427 | + } | |
| 2428 | + } | |
| 2429 | + } | |
| 2430 | + | |
| 2431 | + ide_state[0].cmd = val; | |
| 2365 | 2432 | } |
| 2366 | 2433 | |
| 2367 | 2434 | void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) |
| ... | ... | @@ -2439,14 +2506,17 @@ void ide_init(void) |
| 2439 | 2506 | s->bs = bs_table[i]; |
| 2440 | 2507 | if (s->bs) { |
| 2441 | 2508 | bdrv_get_geometry(s->bs, &nb_sectors); |
| 2442 | - cylinders = nb_sectors / (16 * 63); | |
| 2443 | - if (cylinders > 16383) | |
| 2444 | - cylinders = 16383; | |
| 2445 | - else if (cylinders < 2) | |
| 2446 | - cylinders = 2; | |
| 2447 | - s->cylinders = cylinders; | |
| 2448 | - s->heads = 16; | |
| 2449 | - s->sectors = 63; | |
| 2509 | + if (s->cylinders == 0) { | |
| 2510 | + /* if no geometry, use a LBA compatible one */ | |
| 2511 | + cylinders = nb_sectors / (16 * 63); | |
| 2512 | + if (cylinders > 16383) | |
| 2513 | + cylinders = 16383; | |
| 2514 | + else if (cylinders < 2) | |
| 2515 | + cylinders = 2; | |
| 2516 | + s->cylinders = cylinders; | |
| 2517 | + s->heads = 16; | |
| 2518 | + s->sectors = 63; | |
| 2519 | + } | |
| 2450 | 2520 | s->nb_sectors = nb_sectors; |
| 2451 | 2521 | } |
| 2452 | 2522 | s->irq = 14; |
| ... | ... | @@ -2465,34 +2535,402 @@ void ide_init(void) |
| 2465 | 2535 | } |
| 2466 | 2536 | |
| 2467 | 2537 | /***********************************************************/ |
| 2468 | -/* simulate reset (stop qemu) */ | |
| 2538 | +/* keyboard emulation */ | |
| 2539 | + | |
| 2540 | +/* Keyboard Controller Commands */ | |
| 2541 | +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ | |
| 2542 | +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ | |
| 2543 | +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ | |
| 2544 | +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ | |
| 2545 | +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ | |
| 2546 | +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ | |
| 2547 | +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ | |
| 2548 | +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ | |
| 2549 | +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ | |
| 2550 | +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ | |
| 2551 | +#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */ | |
| 2552 | +#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */ | |
| 2553 | +#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */ | |
| 2554 | +#define KBD_CCMD_WRITE_OBUF 0xD2 | |
| 2555 | +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if | |
| 2556 | + initiated by the auxiliary device */ | |
| 2557 | +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ | |
| 2558 | +#define KBD_CCMD_ENABLE_A20 0xDD | |
| 2559 | +#define KBD_CCMD_DISABLE_A20 0xDF | |
| 2560 | +#define KBD_CCMD_RESET 0xFE | |
| 2561 | + | |
| 2562 | +/* Keyboard Commands */ | |
| 2563 | +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ | |
| 2564 | +#define KBD_CMD_ECHO 0xEE | |
| 2565 | +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ | |
| 2566 | +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ | |
| 2567 | +#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ | |
| 2568 | +#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ | |
| 2569 | +#define KBD_CMD_RESET 0xFF /* Reset */ | |
| 2570 | + | |
| 2571 | +/* Keyboard Replies */ | |
| 2572 | +#define KBD_REPLY_POR 0xAA /* Power on reset */ | |
| 2573 | +#define KBD_REPLY_ACK 0xFA /* Command ACK */ | |
| 2574 | +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ | |
| 2575 | + | |
| 2576 | +/* Status Register Bits */ | |
| 2577 | +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ | |
| 2578 | +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ | |
| 2579 | +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ | |
| 2580 | +#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ | |
| 2581 | +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ | |
| 2582 | +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ | |
| 2583 | +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ | |
| 2584 | +#define KBD_STAT_PERR 0x80 /* Parity error */ | |
| 2585 | + | |
| 2586 | +/* Controller Mode Register Bits */ | |
| 2587 | +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ | |
| 2588 | +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ | |
| 2589 | +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ | |
| 2590 | +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ | |
| 2591 | +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ | |
| 2592 | +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ | |
| 2593 | +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ | |
| 2594 | +#define KBD_MODE_RFU 0x80 | |
| 2595 | + | |
| 2596 | +/* Mouse Commands */ | |
| 2597 | +#define AUX_SET_RES 0xE8 /* Set resolution */ | |
| 2598 | +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ | |
| 2599 | +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ | |
| 2600 | +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ | |
| 2601 | +#define AUX_SET_STREAM 0xEA /* Set stream mode */ | |
| 2602 | +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ | |
| 2603 | +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ | |
| 2604 | +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ | |
| 2605 | +#define AUX_RESET 0xFF /* Reset aux device */ | |
| 2606 | +#define AUX_ACK 0xFA /* Command byte ACK. */ | |
| 2607 | + | |
| 2608 | +#define KBD_QUEUE_SIZE 64 | |
| 2609 | + | |
| 2610 | +typedef struct { | |
| 2611 | + uint8_t data[KBD_QUEUE_SIZE]; | |
| 2612 | + int rptr, wptr, count; | |
| 2613 | +} KBDQueue; | |
| 2614 | + | |
| 2615 | +enum KBDWriteState { | |
| 2616 | + KBD_STATE_CMD = 0, | |
| 2617 | + KBD_STATE_LED, | |
| 2618 | +}; | |
| 2469 | 2619 | |
| 2620 | +typedef struct KBDState { | |
| 2621 | + KBDQueue queues[2]; | |
| 2622 | + uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ | |
| 2623 | + uint8_t status; | |
| 2624 | + uint8_t mode; | |
| 2625 | + int kbd_write_cmd; | |
| 2626 | + int scan_enabled; | |
| 2627 | +} KBDState; | |
| 2628 | + | |
| 2629 | +KBDState kbd_state; | |
| 2470 | 2630 | int reset_requested; |
| 2631 | +int a20_enabled; | |
| 2632 | + | |
| 2633 | +static void kbd_update_irq(KBDState *s) | |
| 2634 | +{ | |
| 2635 | + int level; | |
| 2636 | + | |
| 2637 | + level = ((s->status & KBD_STAT_OBF) && (s->mode & KBD_MODE_KBD_INT)); | |
| 2638 | + pic_set_irq(1, level); | |
| 2639 | + | |
| 2640 | + level = ((s->status & KBD_STAT_MOUSE_OBF) && (s->mode & KBD_MODE_MOUSE_INT)); | |
| 2641 | + pic_set_irq(12, level); | |
| 2642 | +} | |
| 2643 | + | |
| 2644 | +static void kbd_queue(KBDState *s, int b, int aux) | |
| 2645 | +{ | |
| 2646 | + KBDQueue *q = &kbd_state.queues[aux]; | |
| 2647 | + | |
| 2648 | + if (q->count >= KBD_QUEUE_SIZE) | |
| 2649 | + return; | |
| 2650 | + q->data[q->wptr] = b; | |
| 2651 | + if (++q->wptr == KBD_QUEUE_SIZE) | |
| 2652 | + q->wptr = 0; | |
| 2653 | + q->count++; | |
| 2654 | + s->status |= KBD_STAT_OBF; | |
| 2655 | + if (aux) | |
| 2656 | + s->status |= KBD_STAT_MOUSE_OBF; | |
| 2657 | + kbd_update_irq(s); | |
| 2658 | +} | |
| 2471 | 2659 | |
| 2472 | 2660 | uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
| 2473 | 2661 | { |
| 2474 | - return 0; | |
| 2662 | + KBDState *s = &kbd_state; | |
| 2663 | + int val; | |
| 2664 | + val = s->status; | |
| 2665 | +#if defined(DEBUG_KBD) && 0 | |
| 2666 | + printf("kbd: read status=0x%02x\n", val); | |
| 2667 | +#endif | |
| 2668 | + return val; | |
| 2475 | 2669 | } |
| 2476 | 2670 | |
| 2477 | 2671 | void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2478 | 2672 | { |
| 2673 | + KBDState *s = &kbd_state; | |
| 2674 | + | |
| 2675 | +#ifdef DEBUG_KBD | |
| 2676 | + printf("kbd: write cmd=0x%02x\n", val); | |
| 2677 | +#endif | |
| 2479 | 2678 | switch(val) { |
| 2480 | - case 0xfe: | |
| 2679 | + case KBD_CCMD_READ_MODE: | |
| 2680 | + kbd_queue(s, s->mode, 0); | |
| 2681 | + break; | |
| 2682 | + case KBD_CCMD_WRITE_MODE: | |
| 2683 | + case KBD_CCMD_WRITE_OBUF: | |
| 2684 | + case KBD_CCMD_WRITE_AUX_OBUF: | |
| 2685 | + case KBD_CCMD_WRITE_MOUSE: | |
| 2686 | + case KBD_CCMD_WRITE_OUTPORT: | |
| 2687 | + s->write_cmd = val; | |
| 2688 | + break; | |
| 2689 | + case KBD_CCMD_MOUSE_DISABLE: | |
| 2690 | + s->mode |= KBD_MODE_DISABLE_MOUSE; | |
| 2691 | + break; | |
| 2692 | + case KBD_CCMD_MOUSE_ENABLE: | |
| 2693 | + s->mode &= ~KBD_MODE_DISABLE_MOUSE; | |
| 2694 | + break; | |
| 2695 | + case KBD_CCMD_TEST_MOUSE: | |
| 2696 | + kbd_queue(s, 0x00, 0); | |
| 2697 | + break; | |
| 2698 | + case KBD_CCMD_SELF_TEST: | |
| 2699 | + s->status |= KBD_STAT_SELFTEST; | |
| 2700 | + kbd_queue(s, 0x55, 0); | |
| 2701 | + break; | |
| 2702 | + case KBD_CCMD_KBD_TEST: | |
| 2703 | + kbd_queue(s, 0x00, 0); | |
| 2704 | + break; | |
| 2705 | + case KBD_CCMD_KBD_DISABLE: | |
| 2706 | + s->mode |= KBD_MODE_DISABLE_KBD; | |
| 2707 | + break; | |
| 2708 | + case KBD_CCMD_KBD_ENABLE: | |
| 2709 | + s->mode &= ~KBD_MODE_DISABLE_KBD; | |
| 2710 | + break; | |
| 2711 | + case KBD_CCMD_READ_INPORT: | |
| 2712 | + kbd_queue(s, 0x00, 0); | |
| 2713 | + break; | |
| 2714 | + case KBD_CCMD_READ_OUTPORT: | |
| 2715 | + /* XXX: check that */ | |
| 2716 | + val = 0x01 | (a20_enabled << 1); | |
| 2717 | + if (s->status & KBD_STAT_OBF) | |
| 2718 | + val |= 0x10; | |
| 2719 | + if (s->status & KBD_STAT_MOUSE_OBF) | |
| 2720 | + val |= 0x20; | |
| 2721 | + kbd_queue(s, val, 0); | |
| 2722 | + break; | |
| 2723 | + case KBD_CCMD_ENABLE_A20: | |
| 2724 | + a20_enabled = 1; | |
| 2725 | + break; | |
| 2726 | + case KBD_CCMD_DISABLE_A20: | |
| 2727 | + a20_enabled = 0; | |
| 2728 | + break; | |
| 2729 | + case KBD_CCMD_RESET: | |
| 2481 | 2730 | reset_requested = 1; |
| 2482 | 2731 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
| 2483 | 2732 | break; |
| 2484 | 2733 | default: |
| 2734 | + fprintf(stderr, "vl: unsupported keyboard cmd=0x%02x\n", val); | |
| 2735 | + break; | |
| 2736 | + } | |
| 2737 | +} | |
| 2738 | + | |
| 2739 | +uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | |
| 2740 | +{ | |
| 2741 | + KBDState *s = &kbd_state; | |
| 2742 | + KBDQueue *q; | |
| 2743 | + int val; | |
| 2744 | + | |
| 2745 | + q = &s->queues[1]; /* first check AUX data */ | |
| 2746 | + if (q->count == 0) | |
| 2747 | + q = &s->queues[0]; /* then check KBD data */ | |
| 2748 | + if (q->count == 0) { | |
| 2749 | + /* XXX: return something else ? */ | |
| 2750 | + val = 0; | |
| 2751 | + } else { | |
| 2752 | + val = q->data[q->rptr]; | |
| 2753 | + if (++q->rptr == KBD_QUEUE_SIZE) | |
| 2754 | + q->rptr = 0; | |
| 2755 | + q->count--; | |
| 2756 | + } | |
| 2757 | + if (s->queues[1].count == 0) { | |
| 2758 | + s->status &= ~KBD_STAT_MOUSE_OBF; | |
| 2759 | + if (s->queues[0].count == 0) | |
| 2760 | + s->status &= ~KBD_STAT_OBF; | |
| 2761 | + kbd_update_irq(s); | |
| 2762 | + } | |
| 2763 | + | |
| 2764 | +#ifdef DEBUG_KBD | |
| 2765 | + printf("kbd: read data=0x%02x\n", val); | |
| 2766 | +#endif | |
| 2767 | + return val; | |
| 2768 | +} | |
| 2769 | + | |
| 2770 | +static void kbd_reset_keyboard(KBDState *s) | |
| 2771 | +{ | |
| 2772 | + s->scan_enabled = 1; | |
| 2773 | +} | |
| 2774 | + | |
| 2775 | +static void kbd_write_keyboard(KBDState *s, int val) | |
| 2776 | +{ | |
| 2777 | + switch(s->kbd_write_cmd) { | |
| 2778 | + default: | |
| 2779 | + case -1: | |
| 2780 | + switch(val) { | |
| 2781 | + case 0x00: | |
| 2782 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2783 | + break; | |
| 2784 | + case 0x05: | |
| 2785 | + kbd_queue(s, KBD_REPLY_RESEND, 0); | |
| 2786 | + break; | |
| 2787 | + case KBD_CMD_ECHO: | |
| 2788 | + kbd_queue(s, KBD_CMD_ECHO, 0); | |
| 2789 | + break; | |
| 2790 | + case KBD_CMD_ENABLE: | |
| 2791 | + s->scan_enabled = 1; | |
| 2792 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2793 | + break; | |
| 2794 | + case KBD_CMD_SET_LEDS: | |
| 2795 | + case KBD_CMD_SET_RATE: | |
| 2796 | + s->kbd_write_cmd = val; | |
| 2797 | + break; | |
| 2798 | + case KBD_CMD_RESET_DISABLE: | |
| 2799 | + kbd_reset_keyboard(s); | |
| 2800 | + s->scan_enabled = 0; | |
| 2801 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2802 | + break; | |
| 2803 | + case KBD_CMD_RESET_ENABLE: | |
| 2804 | + kbd_reset_keyboard(s); | |
| 2805 | + s->scan_enabled = 1; | |
| 2806 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2807 | + break; | |
| 2808 | + case KBD_CMD_RESET: | |
| 2809 | + kbd_reset_keyboard(s); | |
| 2810 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2811 | + kbd_queue(s, KBD_REPLY_POR, 0); | |
| 2812 | + break; | |
| 2813 | + default: | |
| 2814 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2815 | + break; | |
| 2816 | + } | |
| 2817 | + break; | |
| 2818 | + case KBD_CMD_SET_LEDS: | |
| 2819 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2820 | + break; | |
| 2821 | + case KBD_CMD_SET_RATE: | |
| 2822 | + kbd_queue(s, KBD_REPLY_ACK, 0); | |
| 2823 | + break; | |
| 2824 | + } | |
| 2825 | + s->kbd_write_cmd = -1; | |
| 2826 | +} | |
| 2827 | + | |
| 2828 | +void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2829 | +{ | |
| 2830 | + KBDState *s = &kbd_state; | |
| 2831 | + | |
| 2832 | +#ifdef DEBUG_KBD | |
| 2833 | + printf("kbd: write data=0x%02x\n", val); | |
| 2834 | +#endif | |
| 2835 | + | |
| 2836 | + switch(s->write_cmd) { | |
| 2837 | + case 0: | |
| 2838 | + kbd_write_keyboard(s, val); | |
| 2839 | + break; | |
| 2840 | + case KBD_CCMD_WRITE_MODE: | |
| 2841 | + s->mode = val; | |
| 2842 | + kbd_update_irq(s); | |
| 2843 | + break; | |
| 2844 | + case KBD_CCMD_WRITE_OBUF: | |
| 2845 | + kbd_queue(s, val, 0); | |
| 2846 | + break; | |
| 2847 | + case KBD_CCMD_WRITE_AUX_OBUF: | |
| 2848 | + kbd_queue(s, val, 1); | |
| 2849 | + break; | |
| 2850 | + case KBD_CCMD_WRITE_OUTPORT: | |
| 2851 | + a20_enabled = (val >> 1) & 1; | |
| 2852 | + if (!(val & 1)) { | |
| 2853 | + reset_requested = 1; | |
| 2854 | + cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 2855 | + } | |
| 2856 | + break; | |
| 2857 | + default: | |
| 2485 | 2858 | break; |
| 2486 | 2859 | } |
| 2860 | + s->write_cmd = 0; | |
| 2861 | +} | |
| 2862 | + | |
| 2863 | +void kbd_reset(KBDState *s) | |
| 2864 | +{ | |
| 2865 | + KBDQueue *q; | |
| 2866 | + int i; | |
| 2867 | + | |
| 2868 | + s->kbd_write_cmd = -1; | |
| 2869 | + s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; | |
| 2870 | + s->status = KBD_MODE_SYS | KBD_MODE_NO_KEYLOCK; | |
| 2871 | + for(i = 0; i < 2; i++) { | |
| 2872 | + q = &s->queues[i]; | |
| 2873 | + q->rptr = 0; | |
| 2874 | + q->wptr = 0; | |
| 2875 | + q->count = 0; | |
| 2876 | + } | |
| 2487 | 2877 | } |
| 2488 | 2878 | |
| 2489 | 2879 | void kbd_init(void) |
| 2490 | 2880 | { |
| 2881 | + kbd_reset(&kbd_state); | |
| 2882 | + register_ioport_read(0x60, 1, kbd_read_data, 1); | |
| 2883 | + register_ioport_write(0x60, 1, kbd_write_data, 1); | |
| 2491 | 2884 | register_ioport_read(0x64, 1, kbd_read_status, 1); |
| 2492 | 2885 | register_ioport_write(0x64, 1, kbd_write_command, 1); |
| 2493 | 2886 | } |
| 2494 | 2887 | |
| 2495 | 2888 | /***********************************************************/ |
| 2889 | +/* Bochs BIOS debug ports */ | |
| 2890 | + | |
| 2891 | +void bochs_bios_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2892 | +{ | |
| 2893 | + switch(addr) { | |
| 2894 | + /* Bochs BIOS messages */ | |
| 2895 | + case 0x400: | |
| 2896 | + case 0x401: | |
| 2897 | + fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val); | |
| 2898 | + exit(1); | |
| 2899 | + case 0x402: | |
| 2900 | + case 0x403: | |
| 2901 | +#ifdef DEBUG_BIOS | |
| 2902 | + fprintf(stderr, "%c", val); | |
| 2903 | +#endif | |
| 2904 | + break; | |
| 2905 | + | |
| 2906 | + /* LGPL'ed VGA BIOS messages */ | |
| 2907 | + case 0x501: | |
| 2908 | + case 0x502: | |
| 2909 | + fprintf(stderr, "VGA BIOS panic, line %d\n", val); | |
| 2910 | + exit(1); | |
| 2911 | + case 0x500: | |
| 2912 | + case 0x503: | |
| 2913 | +#ifdef DEBUG_BIOS | |
| 2914 | + fprintf(stderr, "%c", val); | |
| 2915 | +#endif | |
| 2916 | + break; | |
| 2917 | + } | |
| 2918 | +} | |
| 2919 | + | |
| 2920 | +void bochs_bios_init(void) | |
| 2921 | +{ | |
| 2922 | + register_ioport_write(0x400, 1, bochs_bios_write, 2); | |
| 2923 | + register_ioport_write(0x401, 1, bochs_bios_write, 2); | |
| 2924 | + register_ioport_write(0x402, 1, bochs_bios_write, 1); | |
| 2925 | + register_ioport_write(0x403, 1, bochs_bios_write, 1); | |
| 2926 | + | |
| 2927 | + register_ioport_write(0x501, 1, bochs_bios_write, 2); | |
| 2928 | + register_ioport_write(0x502, 1, bochs_bios_write, 2); | |
| 2929 | + register_ioport_write(0x500, 1, bochs_bios_write, 1); | |
| 2930 | + register_ioport_write(0x503, 1, bochs_bios_write, 1); | |
| 2931 | +} | |
| 2932 | + | |
| 2933 | +/***********************************************************/ | |
| 2496 | 2934 | /* cpu signal handler */ |
| 2497 | 2935 | static void host_segv_handler(int host_signum, siginfo_t *info, |
| 2498 | 2936 | void *puc) |
| ... | ... | @@ -2625,7 +3063,7 @@ int main_loop(void *opaque) |
| 2625 | 3063 | void help(void) |
| 2626 | 3064 | { |
| 2627 | 3065 | printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
| 2628 | - "usage: vl [options] bzImage [kernel parameters...]\n" | |
| 3066 | + "usage: vl [options] [bzImage [kernel parameters...]]\n" | |
| 2629 | 3067 | "\n" |
| 2630 | 3068 | "'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
| 2631 | 3069 | "to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
| ... | ... | @@ -2638,10 +3076,12 @@ void help(void) |
| 2638 | 3076 | "-m megs set virtual RAM size to megs MB\n" |
| 2639 | 3077 | "-n script set network init script [default=%s]\n" |
| 2640 | 3078 | "\n" |
| 2641 | - "Debug options:\n" | |
| 3079 | + "Debug/Expert options:\n" | |
| 2642 | 3080 | "-s wait gdb connection to port %d\n" |
| 2643 | 3081 | "-p port change gdb connection port\n" |
| 2644 | 3082 | "-d output log in /tmp/vl.log\n" |
| 3083 | + "-hdachs c,h,s force hard disk 0 geometry for non LBA disk images\n" | |
| 3084 | + "-L path set the directory for the BIOS and VGA BIOS\n" | |
| 2645 | 3085 | "\n" |
| 2646 | 3086 | "During emulation, use C-a h to get terminal commands:\n", |
| 2647 | 3087 | DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
| ... | ... | @@ -2654,13 +3094,14 @@ struct option long_options[] = { |
| 2654 | 3094 | { "hda", 1, NULL, 0, }, |
| 2655 | 3095 | { "hdb", 1, NULL, 0, }, |
| 2656 | 3096 | { "snapshot", 0, NULL, 0, }, |
| 3097 | + { "hdachs", 1, NULL, 0, }, | |
| 2657 | 3098 | { NULL, 0, NULL, 0 }, |
| 2658 | 3099 | }; |
| 2659 | 3100 | |
| 2660 | 3101 | int main(int argc, char **argv) |
| 2661 | 3102 | { |
| 2662 | 3103 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
| 2663 | - int snapshot; | |
| 3104 | + int snapshot, linux_boot; | |
| 2664 | 3105 | struct linux_params *params; |
| 2665 | 3106 | struct sigaction act; |
| 2666 | 3107 | struct itimerval itv; |
| ... | ... | @@ -2678,8 +3119,9 @@ int main(int argc, char **argv) |
| 2678 | 3119 | use_gdbstub = 0; |
| 2679 | 3120 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
| 2680 | 3121 | snapshot = 0; |
| 3122 | + linux_boot = 0; | |
| 2681 | 3123 | for(;;) { |
| 2682 | - c = getopt_long_only(argc, argv, "hm:dn:sp:", long_options, &long_index); | |
| 3124 | + c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); | |
| 2683 | 3125 | if (c == -1) |
| 2684 | 3126 | break; |
| 2685 | 3127 | switch(c) { |
| ... | ... | @@ -2697,6 +3139,28 @@ int main(int argc, char **argv) |
| 2697 | 3139 | case 3: |
| 2698 | 3140 | snapshot = 1; |
| 2699 | 3141 | break; |
| 3142 | + case 4: | |
| 3143 | + { | |
| 3144 | + int cyls, heads, secs; | |
| 3145 | + const char *p; | |
| 3146 | + p = optarg; | |
| 3147 | + cyls = strtol(p, (char **)&p, 0); | |
| 3148 | + if (*p != ',') | |
| 3149 | + goto chs_fail; | |
| 3150 | + p++; | |
| 3151 | + heads = strtol(p, (char **)&p, 0); | |
| 3152 | + if (*p != ',') | |
| 3153 | + goto chs_fail; | |
| 3154 | + p++; | |
| 3155 | + secs = strtol(p, (char **)&p, 0); | |
| 3156 | + if (*p != '\0') | |
| 3157 | + goto chs_fail; | |
| 3158 | + ide_state[0].cylinders = cyls; | |
| 3159 | + ide_state[0].heads = heads; | |
| 3160 | + ide_state[0].sectors = secs; | |
| 3161 | + chs_fail: ; | |
| 3162 | + } | |
| 3163 | + break; | |
| 2700 | 3164 | } |
| 2701 | 3165 | break; |
| 2702 | 3166 | case 'h': |
| ... | ... | @@ -2724,9 +3188,15 @@ int main(int argc, char **argv) |
| 2724 | 3188 | case 'p': |
| 2725 | 3189 | gdbstub_port = atoi(optarg); |
| 2726 | 3190 | break; |
| 3191 | + case 'L': | |
| 3192 | + interp_prefix = optarg; | |
| 3193 | + break; | |
| 2727 | 3194 | } |
| 2728 | 3195 | } |
| 2729 | - if (optind >= argc) | |
| 3196 | + | |
| 3197 | + linux_boot = (optind < argc); | |
| 3198 | + | |
| 3199 | + if (!linux_boot && hd_filename[0] == '\0') | |
| 2730 | 3200 | help(); |
| 2731 | 3201 | |
| 2732 | 3202 | /* init debug */ |
| ... | ... | @@ -2781,46 +3251,119 @@ int main(int argc, char **argv) |
| 2781 | 3251 | } |
| 2782 | 3252 | } |
| 2783 | 3253 | |
| 2784 | - /* now we can load the kernel */ | |
| 2785 | - ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); | |
| 2786 | - if (ret < 0) { | |
| 2787 | - fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); | |
| 2788 | - exit(1); | |
| 2789 | - } | |
| 3254 | + /* init CPU state */ | |
| 3255 | + env = cpu_init(); | |
| 3256 | + global_env = env; | |
| 3257 | + cpu_single_env = env; | |
| 3258 | + | |
| 3259 | + init_ioports(); | |
| 2790 | 3260 | |
| 2791 | - /* load initrd */ | |
| 2792 | - initrd_size = 0; | |
| 2793 | - if (initrd_filename) { | |
| 2794 | - initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); | |
| 2795 | - if (initrd_size < 0) { | |
| 2796 | - fprintf(stderr, "vl: could not load initial ram disk '%s'\n", | |
| 2797 | - initrd_filename); | |
| 3261 | + if (linux_boot) { | |
| 3262 | + /* now we can load the kernel */ | |
| 3263 | + ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); | |
| 3264 | + if (ret < 0) { | |
| 3265 | + fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); | |
| 2798 | 3266 | exit(1); |
| 2799 | 3267 | } |
| 2800 | - } | |
| 3268 | + | |
| 3269 | + /* load initrd */ | |
| 3270 | + initrd_size = 0; | |
| 3271 | + if (initrd_filename) { | |
| 3272 | + initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); | |
| 3273 | + if (initrd_size < 0) { | |
| 3274 | + fprintf(stderr, "vl: could not load initial ram disk '%s'\n", | |
| 3275 | + initrd_filename); | |
| 3276 | + exit(1); | |
| 3277 | + } | |
| 3278 | + } | |
| 3279 | + | |
| 3280 | + /* init kernel params */ | |
| 3281 | + params = (void *)(phys_ram_base + KERNEL_PARAMS_ADDR); | |
| 3282 | + memset(params, 0, sizeof(struct linux_params)); | |
| 3283 | + params->mount_root_rdonly = 0; | |
| 3284 | + params->cl_magic = 0xA33F; | |
| 3285 | + params->cl_offset = params->commandline - (uint8_t *)params; | |
| 3286 | + params->alt_mem_k = (phys_ram_size / 1024) - 1024; | |
| 3287 | + for(i = optind + 1; i < argc; i++) { | |
| 3288 | + if (i != optind + 1) | |
| 3289 | + pstrcat(params->commandline, sizeof(params->commandline), " "); | |
| 3290 | + pstrcat(params->commandline, sizeof(params->commandline), argv[i]); | |
| 3291 | + } | |
| 3292 | + params->loader_type = 0x01; | |
| 3293 | + if (initrd_size > 0) { | |
| 3294 | + params->initrd_start = INITRD_LOAD_ADDR; | |
| 3295 | + params->initrd_size = initrd_size; | |
| 3296 | + } | |
| 3297 | + params->orig_video_lines = 25; | |
| 3298 | + params->orig_video_cols = 80; | |
| 3299 | + | |
| 3300 | + /* setup basic memory access */ | |
| 3301 | + env->cr[0] = 0x00000033; | |
| 3302 | + cpu_x86_init_mmu(env); | |
| 3303 | + | |
| 3304 | + memset(params->idt_table, 0, sizeof(params->idt_table)); | |
| 3305 | + | |
| 3306 | + params->gdt_table[2] = 0x00cf9a000000ffffLL; /* KERNEL_CS */ | |
| 3307 | + params->gdt_table[3] = 0x00cf92000000ffffLL; /* KERNEL_DS */ | |
| 3308 | + | |
| 3309 | + env->idt.base = (void *)params->idt_table; | |
| 3310 | + env->idt.limit = sizeof(params->idt_table) - 1; | |
| 3311 | + env->gdt.base = (void *)params->gdt_table; | |
| 3312 | + env->gdt.limit = sizeof(params->gdt_table) - 1; | |
| 3313 | + | |
| 3314 | + cpu_x86_load_seg(env, R_CS, KERNEL_CS); | |
| 3315 | + cpu_x86_load_seg(env, R_DS, KERNEL_DS); | |
| 3316 | + cpu_x86_load_seg(env, R_ES, KERNEL_DS); | |
| 3317 | + cpu_x86_load_seg(env, R_SS, KERNEL_DS); | |
| 3318 | + cpu_x86_load_seg(env, R_FS, KERNEL_DS); | |
| 3319 | + cpu_x86_load_seg(env, R_GS, KERNEL_DS); | |
| 3320 | + | |
| 3321 | + env->eip = KERNEL_LOAD_ADDR; | |
| 3322 | + env->regs[R_ESI] = KERNEL_PARAMS_ADDR; | |
| 3323 | + env->eflags = 0x2; | |
| 2801 | 3324 | |
| 2802 | - /* init kernel params */ | |
| 2803 | - params = (void *)(phys_ram_base + KERNEL_PARAMS_ADDR); | |
| 2804 | - memset(params, 0, sizeof(struct linux_params)); | |
| 2805 | - params->mount_root_rdonly = 0; | |
| 2806 | - params->cl_magic = 0xA33F; | |
| 2807 | - params->cl_offset = params->commandline - (uint8_t *)params; | |
| 2808 | - params->alt_mem_k = (phys_ram_size / 1024) - 1024; | |
| 2809 | - for(i = optind + 1; i < argc; i++) { | |
| 2810 | - if (i != optind + 1) | |
| 2811 | - pstrcat(params->commandline, sizeof(params->commandline), " "); | |
| 2812 | - pstrcat(params->commandline, sizeof(params->commandline), argv[i]); | |
| 2813 | - } | |
| 2814 | - params->loader_type = 0x01; | |
| 2815 | - if (initrd_size > 0) { | |
| 2816 | - params->initrd_start = INITRD_LOAD_ADDR; | |
| 2817 | - params->initrd_size = initrd_size; | |
| 3325 | + } else { | |
| 3326 | + char buf[1024]; | |
| 3327 | + | |
| 3328 | + /* RAW PC boot */ | |
| 3329 | + | |
| 3330 | + /* BIOS load */ | |
| 3331 | + snprintf(buf, sizeof(buf), "%s/%s", interp_prefix, BIOS_FILENAME); | |
| 3332 | + ret = load_image(buf, phys_ram_base + 0x000f0000); | |
| 3333 | + if (ret != 0x10000) { | |
| 3334 | + fprintf(stderr, "vl: could not load PC bios '%s'\n", BIOS_FILENAME); | |
| 3335 | + exit(1); | |
| 3336 | + } | |
| 3337 | + | |
| 3338 | + /* VGA BIOS load */ | |
| 3339 | + snprintf(buf, sizeof(buf), "%s/%s", interp_prefix, VGABIOS_FILENAME); | |
| 3340 | + ret = load_image(buf, phys_ram_base + 0x000c0000); | |
| 3341 | + | |
| 3342 | + /* setup basic memory access */ | |
| 3343 | + env->cr[0] = 0x60000010; | |
| 3344 | + cpu_x86_init_mmu(env); | |
| 3345 | + | |
| 3346 | + env->idt.limit = 0xffff; | |
| 3347 | + env->gdt.limit = 0xffff; | |
| 3348 | + env->ldt.limit = 0xffff; | |
| 3349 | + | |
| 3350 | + /* not correct (CS base=0xffff0000) */ | |
| 3351 | + cpu_x86_load_seg(env, R_CS, 0xf000); | |
| 3352 | + cpu_x86_load_seg(env, R_DS, 0); | |
| 3353 | + cpu_x86_load_seg(env, R_ES, 0); | |
| 3354 | + cpu_x86_load_seg(env, R_SS, 0); | |
| 3355 | + cpu_x86_load_seg(env, R_FS, 0); | |
| 3356 | + cpu_x86_load_seg(env, R_GS, 0); | |
| 3357 | + | |
| 3358 | + env->eip = 0xfff0; | |
| 3359 | + env->regs[R_EDX] = 0x600; /* indicate P6 processor */ | |
| 3360 | + | |
| 3361 | + env->eflags = 0x2; | |
| 3362 | + | |
| 3363 | + bochs_bios_init(); | |
| 2818 | 3364 | } |
| 2819 | - params->orig_video_lines = 25; | |
| 2820 | - params->orig_video_cols = 80; | |
| 2821 | 3365 | |
| 2822 | 3366 | /* init basic PC hardware */ |
| 2823 | - init_ioports(); | |
| 2824 | 3367 | register_ioport_write(0x80, 1, ioport80_write, 1); |
| 2825 | 3368 | |
| 2826 | 3369 | register_ioport_write(0x3d4, 2, vga_ioport_write, 1); |
| ... | ... | @@ -2843,36 +3386,6 @@ int main(int argc, char **argv) |
| 2843 | 3386 | act.sa_sigaction = host_alarm_handler; |
| 2844 | 3387 | sigaction(SIGALRM, &act, NULL); |
| 2845 | 3388 | |
| 2846 | - /* init CPU state */ | |
| 2847 | - env = cpu_init(); | |
| 2848 | - global_env = env; | |
| 2849 | - cpu_single_env = env; | |
| 2850 | - | |
| 2851 | - /* setup basic memory access */ | |
| 2852 | - env->cr[0] = 0x00000033; | |
| 2853 | - cpu_x86_init_mmu(env); | |
| 2854 | - | |
| 2855 | - memset(params->idt_table, 0, sizeof(params->idt_table)); | |
| 2856 | - | |
| 2857 | - params->gdt_table[2] = 0x00cf9a000000ffffLL; /* KERNEL_CS */ | |
| 2858 | - params->gdt_table[3] = 0x00cf92000000ffffLL; /* KERNEL_DS */ | |
| 2859 | - | |
| 2860 | - env->idt.base = (void *)params->idt_table; | |
| 2861 | - env->idt.limit = sizeof(params->idt_table) - 1; | |
| 2862 | - env->gdt.base = (void *)params->gdt_table; | |
| 2863 | - env->gdt.limit = sizeof(params->gdt_table) - 1; | |
| 2864 | - | |
| 2865 | - cpu_x86_load_seg(env, R_CS, KERNEL_CS); | |
| 2866 | - cpu_x86_load_seg(env, R_DS, KERNEL_DS); | |
| 2867 | - cpu_x86_load_seg(env, R_ES, KERNEL_DS); | |
| 2868 | - cpu_x86_load_seg(env, R_SS, KERNEL_DS); | |
| 2869 | - cpu_x86_load_seg(env, R_FS, KERNEL_DS); | |
| 2870 | - cpu_x86_load_seg(env, R_GS, KERNEL_DS); | |
| 2871 | - | |
| 2872 | - env->eip = KERNEL_LOAD_ADDR; | |
| 2873 | - env->regs[R_ESI] = KERNEL_PARAMS_ADDR; | |
| 2874 | - env->eflags = 0x2; | |
| 2875 | - | |
| 2876 | 3389 | itv.it_interval.tv_sec = 0; |
| 2877 | 3390 | itv.it_interval.tv_usec = 1000; |
| 2878 | 3391 | itv.it_value.tv_sec = 0; | ... | ... |