Commit c45886db19fb117a8ad8a5118572d23a957e5de5
1 parent
ffa65c3b
PowerPC system emulation (Jocelyn Mayer) - PIC poll mode (Jocelyn Mayer) - use C…
…PUState - Floppy support (Jocelyn Mayer) - command line debug (Jocelyn Mayer) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@539 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
382 additions
and
59 deletions
vl.c
| ... | ... | @@ -25,6 +25,7 @@ |
| 25 | 25 | #include <stdio.h> |
| 26 | 26 | #include <stdarg.h> |
| 27 | 27 | #include <string.h> |
| 28 | +#include <ctype.h> | |
| 28 | 29 | #include <getopt.h> |
| 29 | 30 | #include <inttypes.h> |
| 30 | 31 | #include <unistd.h> |
| ... | ... | @@ -80,7 +81,18 @@ |
| 80 | 81 | #define PHYS_RAM_BASE 0xac000000 |
| 81 | 82 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
| 82 | 83 | |
| 84 | +#if defined (TARGET_I386) | |
| 83 | 85 | #define KERNEL_LOAD_ADDR 0x00100000 |
| 86 | +#elif defined (TARGET_PPC) | |
| 87 | +//#define USE_OPEN_FIRMWARE | |
| 88 | +#if defined (USE_OPEN_FIRMWARE) | |
| 89 | +#define KERNEL_LOAD_ADDR 0x01000000 | |
| 90 | +#define KERNEL_STACK_ADDR 0x01200000 | |
| 91 | +#else | |
| 92 | +#define KERNEL_LOAD_ADDR 0x00000000 | |
| 93 | +#define KERNEL_STACK_ADDR 0x00400000 | |
| 94 | +#endif | |
| 95 | +#endif | |
| 84 | 96 | #define INITRD_LOAD_ADDR 0x00400000 |
| 85 | 97 | #define KERNEL_PARAMS_ADDR 0x00090000 |
| 86 | 98 | |
| ... | ... | @@ -206,11 +218,11 @@ struct __attribute__ ((packed)) linux_params { |
| 206 | 218 | |
| 207 | 219 | static const char *bios_dir = CONFIG_QEMU_SHAREDIR; |
| 208 | 220 | char phys_ram_file[1024]; |
| 209 | -CPUX86State *global_env; | |
| 210 | -CPUX86State *cpu_single_env; | |
| 221 | +CPUState *global_env; | |
| 222 | +CPUState *cpu_single_env; | |
| 211 | 223 | IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; |
| 212 | 224 | IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
| 213 | -BlockDriverState *bs_table[MAX_DISKS]; | |
| 225 | +BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD]; | |
| 214 | 226 | int vga_ram_size; |
| 215 | 227 | static DisplayState display_state; |
| 216 | 228 | int nographic; |
| ... | ... | @@ -221,7 +233,7 @@ int boot_device = 'c'; |
| 221 | 233 | /***********************************************************/ |
| 222 | 234 | /* x86 io ports */ |
| 223 | 235 | |
| 224 | -uint32_t default_ioport_readb(CPUX86State *env, uint32_t address) | |
| 236 | +uint32_t default_ioport_readb(CPUState *env, uint32_t address) | |
| 225 | 237 | { |
| 226 | 238 | #ifdef DEBUG_UNUSED_IOPORT |
| 227 | 239 | fprintf(stderr, "inb: port=0x%04x\n", address); |
| ... | ... | @@ -229,7 +241,7 @@ uint32_t default_ioport_readb(CPUX86State *env, uint32_t address) |
| 229 | 241 | return 0xff; |
| 230 | 242 | } |
| 231 | 243 | |
| 232 | -void default_ioport_writeb(CPUX86State *env, uint32_t address, uint32_t data) | |
| 244 | +void default_ioport_writeb(CPUState *env, uint32_t address, uint32_t data) | |
| 233 | 245 | { |
| 234 | 246 | #ifdef DEBUG_UNUSED_IOPORT |
| 235 | 247 | fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data); |
| ... | ... | @@ -237,7 +249,7 @@ void default_ioport_writeb(CPUX86State *env, uint32_t address, uint32_t data) |
| 237 | 249 | } |
| 238 | 250 | |
| 239 | 251 | /* default is to make two byte accesses */ |
| 240 | -uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) | |
| 252 | +uint32_t default_ioport_readw(CPUState *env, uint32_t address) | |
| 241 | 253 | { |
| 242 | 254 | uint32_t data; |
| 243 | 255 | data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](env, address); |
| ... | ... | @@ -245,13 +257,13 @@ uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) |
| 245 | 257 | return data; |
| 246 | 258 | } |
| 247 | 259 | |
| 248 | -void default_ioport_writew(CPUX86State *env, uint32_t address, uint32_t data) | |
| 260 | +void default_ioport_writew(CPUState *env, uint32_t address, uint32_t data) | |
| 249 | 261 | { |
| 250 | 262 | ioport_write_table[0][address & (MAX_IOPORTS - 1)](env, address, data & 0xff); |
| 251 | 263 | ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1, (data >> 8) & 0xff); |
| 252 | 264 | } |
| 253 | 265 | |
| 254 | -uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) | |
| 266 | +uint32_t default_ioport_readl(CPUState *env, uint32_t address) | |
| 255 | 267 | { |
| 256 | 268 | #ifdef DEBUG_UNUSED_IOPORT |
| 257 | 269 | fprintf(stderr, "inl: port=0x%04x\n", address); |
| ... | ... | @@ -259,7 +271,7 @@ uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) |
| 259 | 271 | return 0xffffffff; |
| 260 | 272 | } |
| 261 | 273 | |
| 262 | -void default_ioport_writel(CPUX86State *env, uint32_t address, uint32_t data) | |
| 274 | +void default_ioport_writel(CPUState *env, uint32_t address, uint32_t data) | |
| 263 | 275 | { |
| 264 | 276 | #ifdef DEBUG_UNUSED_IOPORT |
| 265 | 277 | fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data); |
| ... | ... | @@ -345,12 +357,18 @@ char *pstrcat(char *buf, int buf_size, const char *s) |
| 345 | 357 | |
| 346 | 358 | int load_kernel(const char *filename, uint8_t *addr) |
| 347 | 359 | { |
| 348 | - int fd, size, setup_sects; | |
| 360 | + int fd, size; | |
| 361 | +#if defined (TARGET_I386) | |
| 362 | + int setup_sects; | |
| 349 | 363 | uint8_t bootsect[512]; |
| 364 | +#endif | |
| 350 | 365 | |
| 366 | + printf("Load kernel at %p (0x%08x)\n", addr, | |
| 367 | + (uint32_t)addr - (uint32_t)phys_ram_base); | |
| 351 | 368 | fd = open(filename, O_RDONLY); |
| 352 | 369 | if (fd < 0) |
| 353 | 370 | return -1; |
| 371 | +#if defined (TARGET_I386) | |
| 354 | 372 | if (read(fd, bootsect, 512) != 512) |
| 355 | 373 | goto fail; |
| 356 | 374 | setup_sects = bootsect[0x1F1]; |
| ... | ... | @@ -358,6 +376,7 @@ int load_kernel(const char *filename, uint8_t *addr) |
| 358 | 376 | setup_sects = 4; |
| 359 | 377 | /* skip 16 bit setup code */ |
| 360 | 378 | lseek(fd, (setup_sects + 1) * 512, SEEK_SET); |
| 379 | +#endif | |
| 361 | 380 | size = read(fd, addr, 16 * 1024 * 1024); |
| 362 | 381 | if (size < 0) |
| 363 | 382 | goto fail; |
| ... | ... | @@ -385,38 +404,38 @@ int load_image(const char *filename, uint8_t *addr) |
| 385 | 404 | return size; |
| 386 | 405 | } |
| 387 | 406 | |
| 388 | -void cpu_x86_outb(CPUX86State *env, int addr, int val) | |
| 407 | +void cpu_outb(CPUState *env, int addr, int val) | |
| 389 | 408 | { |
| 390 | 409 | ioport_write_table[0][addr & (MAX_IOPORTS - 1)](env, addr, val); |
| 391 | 410 | } |
| 392 | 411 | |
| 393 | -void cpu_x86_outw(CPUX86State *env, int addr, int val) | |
| 412 | +void cpu_outw(CPUState *env, int addr, int val) | |
| 394 | 413 | { |
| 395 | 414 | ioport_write_table[1][addr & (MAX_IOPORTS - 1)](env, addr, val); |
| 396 | 415 | } |
| 397 | 416 | |
| 398 | -void cpu_x86_outl(CPUX86State *env, int addr, int val) | |
| 417 | +void cpu_outl(CPUState *env, int addr, int val) | |
| 399 | 418 | { |
| 400 | 419 | ioport_write_table[2][addr & (MAX_IOPORTS - 1)](env, addr, val); |
| 401 | 420 | } |
| 402 | 421 | |
| 403 | -int cpu_x86_inb(CPUX86State *env, int addr) | |
| 422 | +int cpu_inb(CPUState *env, int addr) | |
| 404 | 423 | { |
| 405 | 424 | return ioport_read_table[0][addr & (MAX_IOPORTS - 1)](env, addr); |
| 406 | 425 | } |
| 407 | 426 | |
| 408 | -int cpu_x86_inw(CPUX86State *env, int addr) | |
| 427 | +int cpu_inw(CPUState *env, int addr) | |
| 409 | 428 | { |
| 410 | 429 | return ioport_read_table[1][addr & (MAX_IOPORTS - 1)](env, addr); |
| 411 | 430 | } |
| 412 | 431 | |
| 413 | -int cpu_x86_inl(CPUX86State *env, int addr) | |
| 432 | +int cpu_inl(CPUState *env, int addr) | |
| 414 | 433 | { |
| 415 | 434 | return ioport_read_table[2][addr & (MAX_IOPORTS - 1)](env, addr); |
| 416 | 435 | } |
| 417 | 436 | |
| 418 | 437 | /***********************************************************/ |
| 419 | -void ioport80_write(CPUX86State *env, uint32_t addr, uint32_t data) | |
| 438 | +void ioport80_write(CPUState *env, uint32_t addr, uint32_t data) | |
| 420 | 439 | { |
| 421 | 440 | } |
| 422 | 441 | |
| ... | ... | @@ -430,6 +449,8 @@ void hw_error(const char *fmt, ...) |
| 430 | 449 | fprintf(stderr, "\n"); |
| 431 | 450 | #ifdef TARGET_I386 |
| 432 | 451 | cpu_x86_dump_state(global_env, stderr, X86_DUMP_FPU | X86_DUMP_CCOP); |
| 452 | +#else | |
| 453 | + cpu_dump_state(global_env, stderr, 0); | |
| 433 | 454 | #endif |
| 434 | 455 | va_end(ap); |
| 435 | 456 | abort(); |
| ... | ... | @@ -438,6 +459,7 @@ void hw_error(const char *fmt, ...) |
| 438 | 459 | /***********************************************************/ |
| 439 | 460 | /* cmos emulation */ |
| 440 | 461 | |
| 462 | +#if defined (TARGET_I386) | |
| 441 | 463 | #define RTC_SECONDS 0 |
| 442 | 464 | #define RTC_SECONDS_ALARM 1 |
| 443 | 465 | #define RTC_MINUTES 2 |
| ... | ... | @@ -463,7 +485,7 @@ void hw_error(const char *fmt, ...) |
| 463 | 485 | uint8_t cmos_data[128]; |
| 464 | 486 | uint8_t cmos_index; |
| 465 | 487 | |
| 466 | -void cmos_ioport_write(CPUX86State *env, uint32_t addr, uint32_t data) | |
| 488 | +void cmos_ioport_write(CPUState *env, uint32_t addr, uint32_t data) | |
| 467 | 489 | { |
| 468 | 490 | if (addr == 0x70) { |
| 469 | 491 | cmos_index = data & 0x7f; |
| ... | ... | @@ -503,7 +525,7 @@ void cmos_ioport_write(CPUX86State *env, uint32_t addr, uint32_t data) |
| 503 | 525 | } |
| 504 | 526 | } |
| 505 | 527 | |
| 506 | -uint32_t cmos_ioport_read(CPUX86State *env, uint32_t addr) | |
| 528 | +uint32_t cmos_ioport_read(CPUState *env, uint32_t addr) | |
| 507 | 529 | { |
| 508 | 530 | int ret; |
| 509 | 531 | |
| ... | ... | @@ -580,6 +602,7 @@ void cmos_init(void) |
| 580 | 602 | |
| 581 | 603 | switch(boot_device) { |
| 582 | 604 | case 'a': |
| 605 | + case 'b': | |
| 583 | 606 | cmos_data[0x3d] = 0x01; /* floppy boot */ |
| 584 | 607 | break; |
| 585 | 608 | default: |
| ... | ... | @@ -595,6 +618,56 @@ void cmos_init(void) |
| 595 | 618 | register_ioport_read(0x70, 2, cmos_ioport_read, 1); |
| 596 | 619 | } |
| 597 | 620 | |
| 621 | +void cmos_register_fd (uint8_t fd0, uint8_t fd1) | |
| 622 | +{ | |
| 623 | + int nb = 0; | |
| 624 | + | |
| 625 | + cmos_data[0x10] = 0; | |
| 626 | + switch (fd0) { | |
| 627 | + case 0: | |
| 628 | + /* 1.44 Mb 3"5 drive */ | |
| 629 | + cmos_data[0x10] |= 0x40; | |
| 630 | + break; | |
| 631 | + case 1: | |
| 632 | + /* 2.88 Mb 3"5 drive */ | |
| 633 | + cmos_data[0x10] |= 0x60; | |
| 634 | + break; | |
| 635 | + case 2: | |
| 636 | + /* 1.2 Mb 5"5 drive */ | |
| 637 | + cmos_data[0x10] |= 0x20; | |
| 638 | + break; | |
| 639 | + } | |
| 640 | + switch (fd1) { | |
| 641 | + case 0: | |
| 642 | + /* 1.44 Mb 3"5 drive */ | |
| 643 | + cmos_data[0x10] |= 0x04; | |
| 644 | + break; | |
| 645 | + case 1: | |
| 646 | + /* 2.88 Mb 3"5 drive */ | |
| 647 | + cmos_data[0x10] |= 0x06; | |
| 648 | + break; | |
| 649 | + case 2: | |
| 650 | + /* 1.2 Mb 5"5 drive */ | |
| 651 | + cmos_data[0x10] |= 0x02; | |
| 652 | + break; | |
| 653 | + } | |
| 654 | + if (fd0 < 3) | |
| 655 | + nb++; | |
| 656 | + if (fd1 < 3) | |
| 657 | + nb++; | |
| 658 | + switch (nb) { | |
| 659 | + case 0: | |
| 660 | + break; | |
| 661 | + case 1: | |
| 662 | + cmos_data[REG_EQUIPMENT_BYTE] |= 0x01; /* 1 drive, ready for boot */ | |
| 663 | + break; | |
| 664 | + case 2: | |
| 665 | + cmos_data[REG_EQUIPMENT_BYTE] |= 0x41; /* 2 drives, ready for boot */ | |
| 666 | + break; | |
| 667 | + } | |
| 668 | +} | |
| 669 | +#endif /* TARGET_I386 */ | |
| 670 | + | |
| 598 | 671 | /***********************************************************/ |
| 599 | 672 | /* 8259 pic emulation */ |
| 600 | 673 | |
| ... | ... | @@ -606,6 +679,7 @@ typedef struct PicState { |
| 606 | 679 | uint8_t priority_add; /* used to compute irq priority */ |
| 607 | 680 | uint8_t irq_base; |
| 608 | 681 | uint8_t read_reg_select; |
| 682 | + uint8_t poll; | |
| 609 | 683 | uint8_t special_mask; |
| 610 | 684 | uint8_t init_state; |
| 611 | 685 | uint8_t auto_eoi; |
| ... | ... | @@ -663,7 +737,7 @@ static int pic_get_irq(PicState *s) |
| 663 | 737 | |
| 664 | 738 | /* raise irq to CPU if necessary. must be called every time the active |
| 665 | 739 | irq may change */ |
| 666 | -static void pic_update_irq(void) | |
| 740 | +void pic_update_irq(void) | |
| 667 | 741 | { |
| 668 | 742 | int irq2, irq; |
| 669 | 743 | |
| ... | ... | @@ -684,7 +758,7 @@ static void pic_update_irq(void) |
| 684 | 758 | /* from master pic */ |
| 685 | 759 | pic_irq_requested = irq; |
| 686 | 760 | } |
| 687 | - cpu_x86_interrupt(global_env, CPU_INTERRUPT_HARD); | |
| 761 | + cpu_interrupt(global_env, CPU_INTERRUPT_HARD); | |
| 688 | 762 | } |
| 689 | 763 | } |
| 690 | 764 | |
| ... | ... | @@ -713,7 +787,7 @@ void pic_set_irq(int irq, int level) |
| 713 | 787 | pic_update_irq(); |
| 714 | 788 | } |
| 715 | 789 | |
| 716 | -int cpu_x86_get_pic_interrupt(CPUX86State *env) | |
| 790 | +int cpu_x86_get_pic_interrupt(CPUState *env) | |
| 717 | 791 | { |
| 718 | 792 | int irq, irq2, intno; |
| 719 | 793 | |
| ... | ... | @@ -742,7 +816,7 @@ int cpu_x86_get_pic_interrupt(CPUX86State *env) |
| 742 | 816 | return intno; |
| 743 | 817 | } |
| 744 | 818 | |
| 745 | -void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 819 | +void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 746 | 820 | { |
| 747 | 821 | PicState *s; |
| 748 | 822 | int priority; |
| ... | ... | @@ -763,10 +837,14 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 763 | 837 | if (val & 0x08) |
| 764 | 838 | hw_error("level sensitive irq not supported"); |
| 765 | 839 | } else if (val & 0x08) { |
| 840 | + if (val & 0x04) { | |
| 841 | + s->poll = 1; | |
| 842 | + } else { | |
| 766 | 843 | if (val & 0x02) |
| 767 | 844 | s->read_reg_select = val & 1; |
| 768 | 845 | if (val & 0x40) |
| 769 | 846 | s->special_mask = (val >> 5) & 1; |
| 847 | + } | |
| 770 | 848 | } else { |
| 771 | 849 | switch(val) { |
| 772 | 850 | case 0x00: |
| ... | ... | @@ -826,7 +904,29 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 826 | 904 | } |
| 827 | 905 | } |
| 828 | 906 | |
| 829 | -uint32_t pic_ioport_read(CPUX86State *env, uint32_t addr1) | |
| 907 | +static uint32_t pic_poll_read (PicState *s, uint32_t addr1) | |
| 908 | +{ | |
| 909 | + int ret; | |
| 910 | + | |
| 911 | + ret = pic_get_irq(s); | |
| 912 | + if (ret >= 0) { | |
| 913 | + if (addr1 >> 7) { | |
| 914 | + pics[0].isr &= ~(1 << 2); | |
| 915 | + pics[0].irr &= ~(1 << 2); | |
| 916 | + } | |
| 917 | + s->irr &= ~(1 << ret); | |
| 918 | + s->isr &= ~(1 << ret); | |
| 919 | + if (addr1 >> 7 || ret != 2) | |
| 920 | + pic_update_irq(); | |
| 921 | + } else { | |
| 922 | + ret = 0x07; | |
| 923 | + pic_update_irq(); | |
| 924 | + } | |
| 925 | + | |
| 926 | + return ret; | |
| 927 | +} | |
| 928 | + | |
| 929 | +uint32_t pic_ioport_read(CPUState *env, uint32_t addr1) | |
| 830 | 930 | { |
| 831 | 931 | PicState *s; |
| 832 | 932 | unsigned int addr; |
| ... | ... | @@ -835,6 +935,10 @@ uint32_t pic_ioport_read(CPUX86State *env, uint32_t addr1) |
| 835 | 935 | addr = addr1; |
| 836 | 936 | s = &pics[addr >> 7]; |
| 837 | 937 | addr &= 1; |
| 938 | + if (s->poll == 1) { | |
| 939 | + ret = pic_poll_read(s, addr1); | |
| 940 | + s->poll = 0; | |
| 941 | + } else { | |
| 838 | 942 | if (addr == 0) { |
| 839 | 943 | if (s->read_reg_select) |
| 840 | 944 | ret = s->isr; |
| ... | ... | @@ -843,18 +947,35 @@ uint32_t pic_ioport_read(CPUX86State *env, uint32_t addr1) |
| 843 | 947 | } else { |
| 844 | 948 | ret = s->imr; |
| 845 | 949 | } |
| 950 | + } | |
| 846 | 951 | #ifdef DEBUG_PIC |
| 847 | 952 | printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret); |
| 848 | 953 | #endif |
| 849 | 954 | return ret; |
| 850 | 955 | } |
| 851 | 956 | |
| 957 | +/* memory mapped interrupt status */ | |
| 958 | +uint32_t pic_intack_read(CPUState *env) | |
| 959 | +{ | |
| 960 | + int ret; | |
| 961 | + | |
| 962 | + ret = pic_poll_read(&pics[0], 0x00); | |
| 963 | + if (ret == 2) | |
| 964 | + ret = pic_poll_read(&pics[1], 0x80) + 8; | |
| 965 | + /* Prepare for ISR read */ | |
| 966 | + pics[0].read_reg_select = 1; | |
| 967 | + | |
| 968 | + return ret; | |
| 969 | +} | |
| 970 | + | |
| 852 | 971 | void pic_init(void) |
| 853 | 972 | { |
| 973 | +#if defined (TARGET_I386) || defined (TARGET_PPC) | |
| 854 | 974 | register_ioport_write(0x20, 2, pic_ioport_write, 1); |
| 855 | 975 | register_ioport_read(0x20, 2, pic_ioport_read, 1); |
| 856 | 976 | register_ioport_write(0xa0, 2, pic_ioport_write, 1); |
| 857 | 977 | register_ioport_read(0xa0, 2, pic_ioport_read, 1); |
| 978 | +#endif | |
| 858 | 979 | } |
| 859 | 980 | |
| 860 | 981 | /***********************************************************/ |
| ... | ... | @@ -1140,7 +1261,7 @@ static inline void pit_load_count(PITChannelState *s, int val) |
| 1140 | 1261 | } |
| 1141 | 1262 | } |
| 1142 | 1263 | |
| 1143 | -void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 1264 | +void pit_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 1144 | 1265 | { |
| 1145 | 1266 | int channel, access; |
| 1146 | 1267 | PITChannelState *s; |
| ... | ... | @@ -1185,7 +1306,7 @@ void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 1185 | 1306 | } |
| 1186 | 1307 | } |
| 1187 | 1308 | |
| 1188 | -uint32_t pit_ioport_read(CPUX86State *env, uint32_t addr) | |
| 1309 | +uint32_t pit_ioport_read(CPUState *env, uint32_t addr) | |
| 1189 | 1310 | { |
| 1190 | 1311 | int ret, count; |
| 1191 | 1312 | PITChannelState *s; |
| ... | ... | @@ -1218,13 +1339,14 @@ uint32_t pit_ioport_read(CPUX86State *env, uint32_t addr) |
| 1218 | 1339 | return ret; |
| 1219 | 1340 | } |
| 1220 | 1341 | |
| 1221 | -void speaker_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 1342 | +#if defined (TARGET_I386) | |
| 1343 | +void speaker_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 1222 | 1344 | { |
| 1223 | 1345 | speaker_data_on = (val >> 1) & 1; |
| 1224 | 1346 | pit_set_gate(&pit_channels[2], val & 1); |
| 1225 | 1347 | } |
| 1226 | 1348 | |
| 1227 | -uint32_t speaker_ioport_read(CPUX86State *env, uint32_t addr) | |
| 1349 | +uint32_t speaker_ioport_read(CPUState *env, uint32_t addr) | |
| 1228 | 1350 | { |
| 1229 | 1351 | int out; |
| 1230 | 1352 | out = pit_get_out(&pit_channels[2]); |
| ... | ... | @@ -1232,6 +1354,7 @@ uint32_t speaker_ioport_read(CPUX86State *env, uint32_t addr) |
| 1232 | 1354 | return (speaker_data_on << 1) | pit_channels[2].gate | (out << 5) | |
| 1233 | 1355 | (dummy_refresh_clock << 4); |
| 1234 | 1356 | } |
| 1357 | +#endif | |
| 1235 | 1358 | |
| 1236 | 1359 | void pit_init(void) |
| 1237 | 1360 | { |
| ... | ... | @@ -1250,8 +1373,10 @@ void pit_init(void) |
| 1250 | 1373 | register_ioport_write(0x40, 4, pit_ioport_write, 1); |
| 1251 | 1374 | register_ioport_read(0x40, 3, pit_ioport_read, 1); |
| 1252 | 1375 | |
| 1376 | +#if defined (TARGET_I386) | |
| 1253 | 1377 | register_ioport_read(0x61, 1, speaker_ioport_read, 1); |
| 1254 | 1378 | register_ioport_write(0x61, 1, speaker_ioport_write, 1); |
| 1379 | +#endif | |
| 1255 | 1380 | } |
| 1256 | 1381 | |
| 1257 | 1382 | /***********************************************************/ |
| ... | ... | @@ -1339,7 +1464,7 @@ void serial_update_irq(void) |
| 1339 | 1464 | } |
| 1340 | 1465 | } |
| 1341 | 1466 | |
| 1342 | -void serial_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 1467 | +void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 1343 | 1468 | { |
| 1344 | 1469 | SerialState *s = &serial_ports[0]; |
| 1345 | 1470 | unsigned char ch; |
| ... | ... | @@ -1396,7 +1521,7 @@ void serial_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 1396 | 1521 | } |
| 1397 | 1522 | } |
| 1398 | 1523 | |
| 1399 | -uint32_t serial_ioport_read(CPUX86State *env, uint32_t addr) | |
| 1524 | +uint32_t serial_ioport_read(CPUState *env, uint32_t addr) | |
| 1400 | 1525 | { |
| 1401 | 1526 | SerialState *s = &serial_ports[0]; |
| 1402 | 1527 | uint32_t ret; |
| ... | ... | @@ -1458,23 +1583,124 @@ uint32_t serial_ioport_read(CPUX86State *env, uint32_t addr) |
| 1458 | 1583 | } |
| 1459 | 1584 | |
| 1460 | 1585 | #define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */ |
| 1461 | -static int term_got_escape; | |
| 1586 | +static int term_got_escape, term_command; | |
| 1587 | +static unsigned char term_cmd_buf[128]; | |
| 1588 | + | |
| 1589 | +typedef struct term_cmd_t { | |
| 1590 | + const unsigned char *name; | |
| 1591 | + void (*handler)(unsigned char *params); | |
| 1592 | +} term_cmd_t; | |
| 1593 | + | |
| 1594 | +static void do_change_cdrom (unsigned char *params); | |
| 1595 | +static void do_change_fd0 (unsigned char *params); | |
| 1596 | +static void do_change_fd1 (unsigned char *params); | |
| 1597 | + | |
| 1598 | +static term_cmd_t term_cmds[] = { | |
| 1599 | + { "changecd", &do_change_cdrom, }, | |
| 1600 | + { "changefd0", &do_change_fd0, }, | |
| 1601 | + { "changefd1", &do_change_fd1, }, | |
| 1602 | + { NULL, NULL, }, | |
| 1603 | +}; | |
| 1462 | 1604 | |
| 1463 | 1605 | void term_print_help(void) |
| 1464 | 1606 | { |
| 1465 | 1607 | printf("\n" |
| 1466 | 1608 | "C-a h print this help\n" |
| 1467 | 1609 | "C-a x exit emulatior\n" |
| 1610 | + "C-a d switch on/off debug log\n" | |
| 1468 | 1611 | "C-a s save disk data back to file (if -snapshot)\n" |
| 1469 | 1612 | "C-a b send break (magic sysrq)\n" |
| 1613 | + "C-a c send qemu internal command\n" | |
| 1470 | 1614 | "C-a C-a send C-a\n" |
| 1471 | 1615 | ); |
| 1472 | 1616 | } |
| 1473 | 1617 | |
| 1618 | +static void do_change_cdrom (unsigned char *params) | |
| 1619 | +{ | |
| 1620 | + /* Dunno how to do it... */ | |
| 1621 | +} | |
| 1622 | + | |
| 1623 | +static void do_change_fd (int fd, unsigned char *params) | |
| 1624 | +{ | |
| 1625 | + unsigned char *name_start, *name_end, *ros; | |
| 1626 | + int ro; | |
| 1627 | + | |
| 1628 | + for (name_start = params; | |
| 1629 | + isspace(*name_start); name_start++) | |
| 1630 | + continue; | |
| 1631 | + if (*name_start == '\0') | |
| 1632 | + return; | |
| 1633 | + for (name_end = name_start; | |
| 1634 | + !isspace(*name_end) && *name_end != '\0'; name_end++) | |
| 1635 | + continue; | |
| 1636 | + for (ros = name_end + 1; isspace(*ros); ros++) | |
| 1637 | + continue; | |
| 1638 | + if (ros[0] == 'r' && ros[1] == 'o') | |
| 1639 | + ro = 1; | |
| 1640 | + else | |
| 1641 | + ro = 0; | |
| 1642 | + *name_end = '\0'; | |
| 1643 | + printf("Change fd %d to %s (%s)\n", fd, name_start, params); | |
| 1644 | + fdctrl_disk_change(fd, name_start, ro); | |
| 1645 | +} | |
| 1646 | + | |
| 1647 | +static void do_change_fd0 (unsigned char *params) | |
| 1648 | +{ | |
| 1649 | + do_change_fd(0, params); | |
| 1650 | +} | |
| 1651 | + | |
| 1652 | +static void do_change_fd1 (unsigned char *params) | |
| 1653 | +{ | |
| 1654 | + do_change_fd(1, params); | |
| 1655 | +} | |
| 1656 | + | |
| 1657 | +static void serial_treat_command () | |
| 1658 | +{ | |
| 1659 | + unsigned char *cmd_start, *cmd_end; | |
| 1660 | + int i; | |
| 1661 | + | |
| 1662 | + for (cmd_start = term_cmd_buf; isspace(*cmd_start); cmd_start++) | |
| 1663 | + continue; | |
| 1664 | + for (cmd_end = cmd_start; | |
| 1665 | + !isspace(*cmd_end) && *cmd_end != '\0'; cmd_end++) | |
| 1666 | + continue; | |
| 1667 | + for (i = 0; term_cmds[i].name != NULL; i++) { | |
| 1668 | + if (strlen(term_cmds[i].name) == (cmd_end - cmd_start) && | |
| 1669 | + memcmp(term_cmds[i].name, cmd_start, cmd_end - cmd_start) == 0) { | |
| 1670 | + (*term_cmds[i].handler)(cmd_end + 1); | |
| 1671 | + return; | |
| 1672 | + } | |
| 1673 | + } | |
| 1674 | + *cmd_end = '\0'; | |
| 1675 | + printf("Unknown term command: %s\n", cmd_start); | |
| 1676 | +} | |
| 1677 | + | |
| 1678 | +extern FILE *logfile; | |
| 1679 | + | |
| 1474 | 1680 | /* called when a char is received */ |
| 1475 | 1681 | void serial_received_byte(SerialState *s, int ch) |
| 1476 | 1682 | { |
| 1477 | - if (term_got_escape) { | |
| 1683 | + if (term_command) { | |
| 1684 | + if (ch == '\n' || ch == '\r' || term_command == 127) { | |
| 1685 | + printf("\n"); | |
| 1686 | + serial_treat_command(); | |
| 1687 | + term_command = 0; | |
| 1688 | + } else { | |
| 1689 | + if (ch == 0x7F || ch == 0x08) { | |
| 1690 | + if (term_command > 1) { | |
| 1691 | + term_cmd_buf[--term_command - 1] = '\0'; | |
| 1692 | + printf("\r " | |
| 1693 | + " "); | |
| 1694 | + printf("\r> %s", term_cmd_buf); | |
| 1695 | + } | |
| 1696 | + } else if (ch > 0x1f) { | |
| 1697 | + term_cmd_buf[term_command++ - 1] = ch; | |
| 1698 | + term_cmd_buf[term_command - 1] = '\0'; | |
| 1699 | + printf("\r> %s", term_cmd_buf); | |
| 1700 | + } | |
| 1701 | + fflush(stdout); | |
| 1702 | + } | |
| 1703 | + } else if (term_got_escape) { | |
| 1478 | 1704 | term_got_escape = 0; |
| 1479 | 1705 | switch(ch) { |
| 1480 | 1706 | case 'h': |
| ... | ... | @@ -1498,8 +1724,10 @@ void serial_received_byte(SerialState *s, int ch) |
| 1498 | 1724 | s->lsr |= UART_LSR_BI | UART_LSR_DR; |
| 1499 | 1725 | serial_update_irq(); |
| 1500 | 1726 | break; |
| 1501 | - case 'd': | |
| 1502 | - cpu_set_log(CPU_LOG_ALL); | |
| 1727 | + case 'c': | |
| 1728 | + printf("> "); | |
| 1729 | + fflush(stdout); | |
| 1730 | + term_command = 1; | |
| 1503 | 1731 | break; |
| 1504 | 1732 | case TERM_ESCAPE: |
| 1505 | 1733 | goto send_char; |
| ... | ... | @@ -1521,13 +1749,16 @@ void serial_init(void) |
| 1521 | 1749 | s->lsr = UART_LSR_TEMT | UART_LSR_THRE; |
| 1522 | 1750 | s->iir = UART_IIR_NO_INT; |
| 1523 | 1751 | |
| 1752 | +#if defined(TARGET_I386) || defined (TARGET_PPC) | |
| 1524 | 1753 | register_ioport_write(0x3f8, 8, serial_ioport_write, 1); |
| 1525 | 1754 | register_ioport_read(0x3f8, 8, serial_ioport_read, 1); |
| 1755 | +#endif | |
| 1526 | 1756 | } |
| 1527 | 1757 | |
| 1528 | 1758 | /***********************************************************/ |
| 1529 | 1759 | /* ne2000 emulation */ |
| 1530 | 1760 | |
| 1761 | +#if defined (TARGET_I386) | |
| 1531 | 1762 | #define NE2000_IOPORT 0x300 |
| 1532 | 1763 | #define NE2000_IRQ 9 |
| 1533 | 1764 | |
| ... | ... | @@ -1775,7 +2006,7 @@ void ne2000_receive(NE2000State *s, uint8_t *buf, int size) |
| 1775 | 2006 | ne2000_update_irq(s); |
| 1776 | 2007 | } |
| 1777 | 2008 | |
| 1778 | -void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2009 | +void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 1779 | 2010 | { |
| 1780 | 2011 | NE2000State *s = &ne2000_state; |
| 1781 | 2012 | int offset, page; |
| ... | ... | @@ -1860,7 +2091,7 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 1860 | 2091 | } |
| 1861 | 2092 | } |
| 1862 | 2093 | |
| 1863 | -uint32_t ne2000_ioport_read(CPUX86State *env, uint32_t addr) | |
| 2094 | +uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr) | |
| 1864 | 2095 | { |
| 1865 | 2096 | NE2000State *s = &ne2000_state; |
| 1866 | 2097 | int offset, page, ret; |
| ... | ... | @@ -1901,7 +2132,7 @@ uint32_t ne2000_ioport_read(CPUX86State *env, uint32_t addr) |
| 1901 | 2132 | return ret; |
| 1902 | 2133 | } |
| 1903 | 2134 | |
| 1904 | -void ne2000_asic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2135 | +void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 1905 | 2136 | { |
| 1906 | 2137 | NE2000State *s = &ne2000_state; |
| 1907 | 2138 | uint8_t *p; |
| ... | ... | @@ -1932,7 +2163,7 @@ void ne2000_asic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 1932 | 2163 | } |
| 1933 | 2164 | } |
| 1934 | 2165 | |
| 1935 | -uint32_t ne2000_asic_ioport_read(CPUX86State *env, uint32_t addr) | |
| 2166 | +uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr) | |
| 1936 | 2167 | { |
| 1937 | 2168 | NE2000State *s = &ne2000_state; |
| 1938 | 2169 | uint8_t *p; |
| ... | ... | @@ -1964,12 +2195,12 @@ uint32_t ne2000_asic_ioport_read(CPUX86State *env, uint32_t addr) |
| 1964 | 2195 | return ret; |
| 1965 | 2196 | } |
| 1966 | 2197 | |
| 1967 | -void ne2000_reset_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2198 | +void ne2000_reset_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | |
| 1968 | 2199 | { |
| 1969 | 2200 | /* nothing to do (end of reset pulse) */ |
| 1970 | 2201 | } |
| 1971 | 2202 | |
| 1972 | -uint32_t ne2000_reset_ioport_read(CPUX86State *env, uint32_t addr) | |
| 2203 | +uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr) | |
| 1973 | 2204 | { |
| 1974 | 2205 | ne2000_reset(); |
| 1975 | 2206 | return 0; |
| ... | ... | @@ -1989,6 +2220,25 @@ void ne2000_init(void) |
| 1989 | 2220 | register_ioport_read(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_read, 1); |
| 1990 | 2221 | ne2000_reset(); |
| 1991 | 2222 | } |
| 2223 | +#endif | |
| 2224 | + | |
| 2225 | +/***********************************************************/ | |
| 2226 | +/* PC floppy disk controler emulation glue */ | |
| 2227 | +#define PC_FDC_DMA 0x2 | |
| 2228 | +#define PC_FDC_IRQ 0x6 | |
| 2229 | +#define PC_FDC_BASE 0x3F0 | |
| 2230 | + | |
| 2231 | +static void fdctrl_register (unsigned char **disknames, int ro, | |
| 2232 | + char boot_device) | |
| 2233 | +{ | |
| 2234 | + int i; | |
| 2235 | + | |
| 2236 | + fdctrl_init(PC_FDC_IRQ, PC_FDC_DMA, 0, PC_FDC_BASE, boot_device); | |
| 2237 | + for (i = 0; i < MAX_FD; i++) { | |
| 2238 | + if (disknames[i] != NULL) | |
| 2239 | + fdctrl_disk_change(i, disknames[i], ro); | |
| 2240 | + } | |
| 2241 | +} | |
| 1992 | 2242 | |
| 1993 | 2243 | /***********************************************************/ |
| 1994 | 2244 | /* keyboard emulation */ |
| ... | ... | @@ -2158,18 +2408,18 @@ void kbd_put_keycode(int keycode) |
| 2158 | 2408 | kbd_queue(s, keycode, 0); |
| 2159 | 2409 | } |
| 2160 | 2410 | |
| 2161 | -uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) | |
| 2411 | +uint32_t kbd_read_status(CPUState *env, uint32_t addr) | |
| 2162 | 2412 | { |
| 2163 | 2413 | KBDState *s = &kbd_state; |
| 2164 | 2414 | int val; |
| 2165 | 2415 | val = s->status; |
| 2166 | -#if defined(DEBUG_KBD) && 0 | |
| 2416 | +#if defined(DEBUG_KBD) | |
| 2167 | 2417 | printf("kbd: read status=0x%02x\n", val); |
| 2168 | 2418 | #endif |
| 2169 | 2419 | return val; |
| 2170 | 2420 | } |
| 2171 | 2421 | |
| 2172 | -void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2422 | +void kbd_write_command(CPUState *env, uint32_t addr, uint32_t val) | |
| 2173 | 2423 | { |
| 2174 | 2424 | KBDState *s = &kbd_state; |
| 2175 | 2425 | |
| ... | ... | @@ -2216,22 +2466,28 @@ void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2216 | 2466 | break; |
| 2217 | 2467 | case KBD_CCMD_READ_OUTPORT: |
| 2218 | 2468 | /* XXX: check that */ |
| 2469 | +#ifdef TARGET_I386 | |
| 2219 | 2470 | val = 0x01 | (a20_enabled << 1); |
| 2471 | +#else | |
| 2472 | + val = 0x01; | |
| 2473 | +#endif | |
| 2220 | 2474 | if (s->status & KBD_STAT_OBF) |
| 2221 | 2475 | val |= 0x10; |
| 2222 | 2476 | if (s->status & KBD_STAT_MOUSE_OBF) |
| 2223 | 2477 | val |= 0x20; |
| 2224 | 2478 | kbd_queue(s, val, 0); |
| 2225 | 2479 | break; |
| 2480 | +#ifdef TARGET_I386 | |
| 2226 | 2481 | case KBD_CCMD_ENABLE_A20: |
| 2227 | 2482 | cpu_x86_set_a20(env, 1); |
| 2228 | 2483 | break; |
| 2229 | 2484 | case KBD_CCMD_DISABLE_A20: |
| 2230 | 2485 | cpu_x86_set_a20(env, 0); |
| 2231 | 2486 | break; |
| 2487 | +#endif | |
| 2232 | 2488 | case KBD_CCMD_RESET: |
| 2233 | 2489 | reset_requested = 1; |
| 2234 | - cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 2490 | + cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 2235 | 2491 | break; |
| 2236 | 2492 | case 0xff: |
| 2237 | 2493 | /* ignore that - I don't know what is its use */ |
| ... | ... | @@ -2242,7 +2498,7 @@ void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2242 | 2498 | } |
| 2243 | 2499 | } |
| 2244 | 2500 | |
| 2245 | -uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | |
| 2501 | +uint32_t kbd_read_data(CPUState *env, uint32_t addr) | |
| 2246 | 2502 | { |
| 2247 | 2503 | KBDState *s = &kbd_state; |
| 2248 | 2504 | KBDQueue *q; |
| ... | ... | @@ -2543,7 +2799,7 @@ static void kbd_write_mouse(KBDState *s, int val) |
| 2543 | 2799 | } |
| 2544 | 2800 | } |
| 2545 | 2801 | |
| 2546 | -void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) | |
| 2802 | +void kbd_write_data(CPUState *env, uint32_t addr, uint32_t val) | |
| 2547 | 2803 | { |
| 2548 | 2804 | KBDState *s = &kbd_state; |
| 2549 | 2805 | |
| ... | ... | @@ -2566,10 +2822,12 @@ void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2566 | 2822 | kbd_queue(s, val, 1); |
| 2567 | 2823 | break; |
| 2568 | 2824 | case KBD_CCMD_WRITE_OUTPORT: |
| 2825 | +#ifdef TARGET_I386 | |
| 2569 | 2826 | cpu_x86_set_a20(env, (val >> 1) & 1); |
| 2827 | +#endif | |
| 2570 | 2828 | if (!(val & 1)) { |
| 2571 | 2829 | reset_requested = 1; |
| 2572 | - cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 2830 | + cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 2573 | 2831 | } |
| 2574 | 2832 | break; |
| 2575 | 2833 | case KBD_CCMD_WRITE_MOUSE: |
| ... | ... | @@ -2601,15 +2859,17 @@ void kbd_reset(KBDState *s) |
| 2601 | 2859 | void kbd_init(void) |
| 2602 | 2860 | { |
| 2603 | 2861 | kbd_reset(&kbd_state); |
| 2862 | +#if defined (TARGET_I386) || defined (TARGET_PPC) | |
| 2604 | 2863 | register_ioport_read(0x60, 1, kbd_read_data, 1); |
| 2605 | 2864 | register_ioport_write(0x60, 1, kbd_write_data, 1); |
| 2606 | 2865 | register_ioport_read(0x64, 1, kbd_read_status, 1); |
| 2607 | 2866 | register_ioport_write(0x64, 1, kbd_write_command, 1); |
| 2867 | +#endif | |
| 2608 | 2868 | } |
| 2609 | 2869 | |
| 2610 | 2870 | /***********************************************************/ |
| 2611 | 2871 | /* Bochs BIOS debug ports */ |
| 2612 | - | |
| 2872 | +#ifdef TARGET_I386 | |
| 2613 | 2873 | void bochs_bios_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2614 | 2874 | { |
| 2615 | 2875 | switch(addr) { |
| ... | ... | @@ -2651,6 +2911,7 @@ void bochs_bios_init(void) |
| 2651 | 2911 | register_ioport_write(0x500, 1, bochs_bios_write, 1); |
| 2652 | 2912 | register_ioport_write(0x503, 1, bochs_bios_write, 1); |
| 2653 | 2913 | } |
| 2914 | +#endif | |
| 2654 | 2915 | |
| 2655 | 2916 | /***********************************************************/ |
| 2656 | 2917 | /* dumb display */ |
| ... | ... | @@ -2756,7 +3017,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, |
| 2756 | 3017 | |
| 2757 | 3018 | if (gui_refresh_pending || timer_irq_pending) { |
| 2758 | 3019 | /* just exit from the cpu to have a chance to handle timers */ |
| 2759 | - cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 3020 | + cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 2760 | 3021 | } |
| 2761 | 3022 | } |
| 2762 | 3023 | |
| ... | ... | @@ -2786,7 +3047,10 @@ CPUState *cpu_gdbstub_get_env(void *opaque) |
| 2786 | 3047 | |
| 2787 | 3048 | int main_loop(void *opaque) |
| 2788 | 3049 | { |
| 2789 | - struct pollfd ufds[3], *pf, *serial_ufd, *net_ufd, *gdb_ufd; | |
| 3050 | + struct pollfd ufds[3], *pf, *serial_ufd, *gdb_ufd; | |
| 3051 | +#if defined (TARGET_I386) | |
| 3052 | + struct pollfd *net_ufd; | |
| 3053 | +#endif | |
| 2790 | 3054 | int ret, n, timeout, serial_ok; |
| 2791 | 3055 | uint8_t ch; |
| 2792 | 3056 | CPUState *env = global_env; |
| ... | ... | @@ -2802,7 +3066,10 @@ int main_loop(void *opaque) |
| 2802 | 3066 | serial_ok = 1; |
| 2803 | 3067 | cpu_enable_ticks(); |
| 2804 | 3068 | for(;;) { |
| 2805 | - ret = cpu_x86_exec(env); | |
| 3069 | +#if defined (DO_TB_FLUSH) | |
| 3070 | + tb_flush(); | |
| 3071 | +#endif | |
| 3072 | + ret = cpu_exec(env); | |
| 2806 | 3073 | if (reset_requested) { |
| 2807 | 3074 | ret = EXCP_INTERRUPT; |
| 2808 | 3075 | break; |
| ... | ... | @@ -2825,6 +3092,7 @@ int main_loop(void *opaque) |
| 2825 | 3092 | pf->events = POLLIN; |
| 2826 | 3093 | pf++; |
| 2827 | 3094 | } |
| 3095 | +#if defined (TARGET_I386) | |
| 2828 | 3096 | net_ufd = NULL; |
| 2829 | 3097 | if (net_fd > 0 && ne2000_can_receive(&ne2000_state)) { |
| 2830 | 3098 | net_ufd = pf; |
| ... | ... | @@ -2832,6 +3100,7 @@ int main_loop(void *opaque) |
| 2832 | 3100 | pf->events = POLLIN; |
| 2833 | 3101 | pf++; |
| 2834 | 3102 | } |
| 3103 | +#endif | |
| 2835 | 3104 | gdb_ufd = NULL; |
| 2836 | 3105 | if (gdbstub_fd > 0) { |
| 2837 | 3106 | gdb_ufd = pf; |
| ... | ... | @@ -2851,6 +3120,7 @@ int main_loop(void *opaque) |
| 2851 | 3120 | serial_ok = 0; |
| 2852 | 3121 | } |
| 2853 | 3122 | } |
| 3123 | +#if defined (TARGET_I386) | |
| 2854 | 3124 | if (net_ufd && (net_ufd->revents & POLLIN)) { |
| 2855 | 3125 | uint8_t buf[MAX_ETH_FRAME_SIZE]; |
| 2856 | 3126 | |
| ... | ... | @@ -2863,6 +3133,7 @@ int main_loop(void *opaque) |
| 2863 | 3133 | ne2000_receive(&ne2000_state, buf, n); |
| 2864 | 3134 | } |
| 2865 | 3135 | } |
| 3136 | +#endif | |
| 2866 | 3137 | if (gdb_ufd && (gdb_ufd->revents & POLLIN)) { |
| 2867 | 3138 | uint8_t buf[1]; |
| 2868 | 3139 | /* stop emulation if requested by gdb */ |
| ... | ... | @@ -2876,6 +3147,7 @@ int main_loop(void *opaque) |
| 2876 | 3147 | |
| 2877 | 3148 | /* timer IRQ */ |
| 2878 | 3149 | if (timer_irq_pending) { |
| 3150 | +#if defined (TARGET_I386) | |
| 2879 | 3151 | pic_set_irq(0, 1); |
| 2880 | 3152 | pic_set_irq(0, 0); |
| 2881 | 3153 | timer_irq_pending = 0; |
| ... | ... | @@ -2883,6 +3155,7 @@ int main_loop(void *opaque) |
| 2883 | 3155 | if (cmos_data[RTC_REG_B] & 0x50) { |
| 2884 | 3156 | pic_set_irq(8, 1); |
| 2885 | 3157 | } |
| 3158 | +#endif | |
| 2886 | 3159 | } |
| 2887 | 3160 | |
| 2888 | 3161 | /* VGA */ |
| ... | ... | @@ -2903,6 +3176,7 @@ void help(void) |
| 2903 | 3176 | "'disk_image' is a raw hard image image for IDE hard disk 0\n" |
| 2904 | 3177 | "\n" |
| 2905 | 3178 | "Standard options:\n" |
| 3179 | + "-fda/-fdb file use 'file' as floppy disk 0/1 image\n" | |
| 2906 | 3180 | "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n" |
| 2907 | 3181 | "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" |
| 2908 | 3182 | "-cdrom file use 'file' as IDE cdrom 2 image\n" |
| ... | ... | @@ -2957,6 +3231,8 @@ struct option long_options[] = { |
| 2957 | 3231 | { "hdd", 1, NULL, 0, }, |
| 2958 | 3232 | { "cdrom", 1, NULL, 0, }, |
| 2959 | 3233 | { "boot", 1, NULL, 0, }, |
| 3234 | + { "fda", 1, NULL, 0, }, | |
| 3235 | + { "fdb", 1, NULL, 0, }, | |
| 2960 | 3236 | { NULL, 0, NULL, 0 }, |
| 2961 | 3237 | }; |
| 2962 | 3238 | |
| ... | ... | @@ -2976,23 +3252,29 @@ int main(int argc, char **argv) |
| 2976 | 3252 | { |
| 2977 | 3253 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
| 2978 | 3254 | int snapshot, linux_boot, total_ram_size; |
| 3255 | +#if defined (TARGET_I386) | |
| 2979 | 3256 | struct linux_params *params; |
| 3257 | +#endif | |
| 2980 | 3258 | struct sigaction act; |
| 2981 | 3259 | struct itimerval itv; |
| 2982 | - CPUX86State *env; | |
| 3260 | + CPUState *env; | |
| 2983 | 3261 | const char *initrd_filename; |
| 2984 | - const char *hd_filename[MAX_DISKS]; | |
| 3262 | + const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; | |
| 2985 | 3263 | const char *kernel_filename, *kernel_cmdline; |
| 2986 | 3264 | DisplayState *ds = &display_state; |
| 2987 | 3265 | |
| 2988 | 3266 | /* we never want that malloc() uses mmap() */ |
| 2989 | 3267 | mallopt(M_MMAP_THRESHOLD, 4096 * 1024); |
| 2990 | 3268 | initrd_filename = NULL; |
| 3269 | + for(i = 0; i < MAX_FD; i++) | |
| 3270 | + fd_filename[i] = NULL; | |
| 2991 | 3271 | for(i = 0; i < MAX_DISKS; i++) |
| 2992 | 3272 | hd_filename[i] = NULL; |
| 2993 | 3273 | phys_ram_size = 32 * 1024 * 1024; |
| 2994 | 3274 | vga_ram_size = VGA_RAM_SIZE; |
| 3275 | +#if defined (TARGET_I386) | |
| 2995 | 3276 | pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
| 3277 | +#endif | |
| 2996 | 3278 | use_gdbstub = 0; |
| 2997 | 3279 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
| 2998 | 3280 | snapshot = 0; |
| ... | ... | @@ -3047,9 +3329,11 @@ int main(int argc, char **argv) |
| 3047 | 3329 | case 7: |
| 3048 | 3330 | kernel_cmdline = optarg; |
| 3049 | 3331 | break; |
| 3332 | +#if defined (TARGET_I386) | |
| 3050 | 3333 | case 8: |
| 3051 | 3334 | net_fd = atoi(optarg); |
| 3052 | 3335 | break; |
| 3336 | +#endif | |
| 3053 | 3337 | case 9: |
| 3054 | 3338 | hd_filename[2] = optarg; |
| 3055 | 3339 | break; |
| ... | ... | @@ -3062,11 +3346,18 @@ int main(int argc, char **argv) |
| 3062 | 3346 | break; |
| 3063 | 3347 | case 12: |
| 3064 | 3348 | boot_device = optarg[0]; |
| 3065 | - if (boot_device != 'c' && boot_device != 'd') { | |
| 3349 | + if (boot_device != 'a' && boot_device != 'b' && | |
| 3350 | + boot_device != 'c' && boot_device != 'd') { | |
| 3066 | 3351 | fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device); |
| 3067 | 3352 | exit(1); |
| 3068 | 3353 | } |
| 3069 | 3354 | break; |
| 3355 | + case 13: | |
| 3356 | + fd_filename[0] = optarg; | |
| 3357 | + break; | |
| 3358 | + case 14: | |
| 3359 | + fd_filename[1] = optarg; | |
| 3360 | + break; | |
| 3070 | 3361 | } |
| 3071 | 3362 | break; |
| 3072 | 3363 | case 'h': |
| ... | ... | @@ -3085,9 +3376,11 @@ int main(int argc, char **argv) |
| 3085 | 3376 | case 'd': |
| 3086 | 3377 | cpu_set_log(CPU_LOG_ALL); |
| 3087 | 3378 | break; |
| 3379 | +#if defined (TARGET_I386) | |
| 3088 | 3380 | case 'n': |
| 3089 | 3381 | pstrcpy(network_script, sizeof(network_script), optarg); |
| 3090 | 3382 | break; |
| 3383 | +#endif | |
| 3091 | 3384 | case 's': |
| 3092 | 3385 | use_gdbstub = 1; |
| 3093 | 3386 | break; |
| ... | ... | @@ -3106,7 +3399,8 @@ int main(int argc, char **argv) |
| 3106 | 3399 | |
| 3107 | 3400 | linux_boot = (kernel_filename != NULL); |
| 3108 | 3401 | |
| 3109 | - if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0') | |
| 3402 | + if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' && | |
| 3403 | + fd_filename[0] == '\0') | |
| 3110 | 3404 | help(); |
| 3111 | 3405 | |
| 3112 | 3406 | /* boot to cd by default if no hard disk */ |
| ... | ... | @@ -3124,8 +3418,10 @@ int main(int argc, char **argv) |
| 3124 | 3418 | #endif |
| 3125 | 3419 | |
| 3126 | 3420 | /* init network tun interface */ |
| 3421 | +#if defined (TARGET_I386) | |
| 3127 | 3422 | if (net_fd < 0) |
| 3128 | 3423 | net_init(); |
| 3424 | +#endif | |
| 3129 | 3425 | |
| 3130 | 3426 | /* init the memory */ |
| 3131 | 3427 | total_ram_size = phys_ram_size + vga_ram_size; |
| ... | ... | @@ -3213,6 +3509,7 @@ int main(int argc, char **argv) |
| 3213 | 3509 | } |
| 3214 | 3510 | |
| 3215 | 3511 | /* init kernel params */ |
| 3512 | +#ifdef TARGET_I386 | |
| 3216 | 3513 | params = (void *)(phys_ram_base + KERNEL_PARAMS_ADDR); |
| 3217 | 3514 | memset(params, 0, sizeof(struct linux_params)); |
| 3218 | 3515 | params->mount_root_rdonly = 0; |
| ... | ... | @@ -3256,12 +3553,16 @@ int main(int argc, char **argv) |
| 3256 | 3553 | env->eip = KERNEL_LOAD_ADDR; |
| 3257 | 3554 | env->regs[R_ESI] = KERNEL_PARAMS_ADDR; |
| 3258 | 3555 | env->eflags = 0x2; |
| 3259 | - | |
| 3556 | +#elif defined (TARGET_PPC) | |
| 3557 | + cpu_x86_init_mmu(env); | |
| 3558 | + PPC_init_hw(env, phys_ram_size, KERNEL_LOAD_ADDR, ret, | |
| 3559 | + KERNEL_STACK_ADDR, boot_device); | |
| 3560 | +#endif | |
| 3260 | 3561 | } else { |
| 3261 | 3562 | char buf[1024]; |
| 3262 | 3563 | |
| 3263 | 3564 | /* RAW PC boot */ |
| 3264 | - | |
| 3565 | +#if defined(TARGET_I386) | |
| 3265 | 3566 | /* BIOS load */ |
| 3266 | 3567 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); |
| 3267 | 3568 | ret = load_image(buf, phys_ram_base + 0x000f0000); |
| ... | ... | @@ -3302,6 +3603,19 @@ int main(int argc, char **argv) |
| 3302 | 3603 | env->eflags = 0x2; |
| 3303 | 3604 | |
| 3304 | 3605 | bochs_bios_init(); |
| 3606 | +#elif defined(TARGET_PPC) | |
| 3607 | + cpu_x86_init_mmu(env); | |
| 3608 | + /* allocate ROM */ | |
| 3609 | + // snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); | |
| 3610 | + snprintf(buf, sizeof(buf), "%s", BIOS_FILENAME); | |
| 3611 | + printf("load BIOS at %p\n", phys_ram_base + 0x000f0000); | |
| 3612 | + ret = load_image(buf, phys_ram_base + 0x000f0000); | |
| 3613 | + if (ret != 0x10000) { | |
| 3614 | + fprintf(stderr, "qemu: could not load PPC bios '%s' (%d)\n%m\n", | |
| 3615 | + buf, ret); | |
| 3616 | + exit(1); | |
| 3617 | + } | |
| 3618 | +#endif | |
| 3305 | 3619 | } |
| 3306 | 3620 | |
| 3307 | 3621 | /* terminal init */ |
| ... | ... | @@ -3317,19 +3631,28 @@ int main(int argc, char **argv) |
| 3317 | 3631 | /* init basic PC hardware */ |
| 3318 | 3632 | register_ioport_write(0x80, 1, ioport80_write, 1); |
| 3319 | 3633 | |
| 3320 | - vga_init(ds, phys_ram_base + phys_ram_size, phys_ram_size, | |
| 3634 | + vga_initialize(ds, phys_ram_base + phys_ram_size, phys_ram_size, | |
| 3321 | 3635 | vga_ram_size); |
| 3636 | +#if defined (TARGET_I386) | |
| 3322 | 3637 | cmos_init(); |
| 3638 | +#endif | |
| 3323 | 3639 | pic_init(); |
| 3324 | 3640 | pit_init(); |
| 3325 | 3641 | serial_init(); |
| 3642 | +#if defined (TARGET_I386) | |
| 3326 | 3643 | ne2000_init(); |
| 3644 | +#endif | |
| 3327 | 3645 | ide_init(); |
| 3328 | 3646 | kbd_init(); |
| 3329 | 3647 | AUD_init(); |
| 3330 | 3648 | DMA_init(); |
| 3649 | +#if defined (TARGET_I386) | |
| 3331 | 3650 | SB16_init(); |
| 3332 | - | |
| 3651 | +#endif | |
| 3652 | +#if defined (TARGET_PPC) | |
| 3653 | + PPC_end_init(); | |
| 3654 | +#endif | |
| 3655 | + fdctrl_register((unsigned char **)fd_filename, snapshot, boot_device); | |
| 3333 | 3656 | /* setup cpu signal handlers for MMU / self modifying code handling */ |
| 3334 | 3657 | sigfillset(&act.sa_mask); |
| 3335 | 3658 | act.sa_flags = SA_SIGINFO; | ... | ... |