Commit 6e44ba7fa22389896be6c21b68b53778a0775821
1 parent
6986f88c
cmos return current date - current irq priority in PIC (L4 Pistachio support) - help fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@557 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
125 additions
and
68 deletions
vl.c
| ... | ... | @@ -525,6 +525,28 @@ void cmos_ioport_write(CPUState *env, uint32_t addr, uint32_t data) |
| 525 | 525 | } |
| 526 | 526 | } |
| 527 | 527 | |
| 528 | +static inline int to_bcd(int a) | |
| 529 | +{ | |
| 530 | + return ((a / 10) << 4) | (a % 10); | |
| 531 | +} | |
| 532 | + | |
| 533 | +static void cmos_update_time(void) | |
| 534 | +{ | |
| 535 | + struct tm *tm; | |
| 536 | + time_t ti; | |
| 537 | + | |
| 538 | + ti = time(NULL); | |
| 539 | + tm = gmtime(&ti); | |
| 540 | + cmos_data[RTC_SECONDS] = to_bcd(tm->tm_sec); | |
| 541 | + cmos_data[RTC_MINUTES] = to_bcd(tm->tm_min); | |
| 542 | + cmos_data[RTC_HOURS] = to_bcd(tm->tm_hour); | |
| 543 | + cmos_data[RTC_DAY_OF_WEEK] = to_bcd(tm->tm_wday); | |
| 544 | + cmos_data[RTC_DAY_OF_MONTH] = to_bcd(tm->tm_mday); | |
| 545 | + cmos_data[RTC_MONTH] = to_bcd(tm->tm_mon + 1); | |
| 546 | + cmos_data[RTC_YEAR] = to_bcd(tm->tm_year % 100); | |
| 547 | + cmos_data[REG_IBM_CENTURY_BYTE] = to_bcd((tm->tm_year / 100) + 19); | |
| 548 | +} | |
| 549 | + | |
| 528 | 550 | uint32_t cmos_ioport_read(CPUState *env, uint32_t addr) |
| 529 | 551 | { |
| 530 | 552 | int ret; |
| ... | ... | @@ -532,17 +554,32 @@ uint32_t cmos_ioport_read(CPUState *env, uint32_t addr) |
| 532 | 554 | if (addr == 0x70) { |
| 533 | 555 | return 0xff; |
| 534 | 556 | } else { |
| 535 | - ret = cmos_data[cmos_index]; | |
| 536 | 557 | switch(cmos_index) { |
| 558 | + case RTC_SECONDS: | |
| 559 | + case RTC_MINUTES: | |
| 560 | + case RTC_HOURS: | |
| 561 | + case RTC_DAY_OF_WEEK: | |
| 562 | + case RTC_DAY_OF_MONTH: | |
| 563 | + case RTC_MONTH: | |
| 564 | + case RTC_YEAR: | |
| 565 | + case REG_IBM_CENTURY_BYTE: | |
| 566 | + cmos_update_time(); | |
| 567 | + ret = cmos_data[cmos_index]; | |
| 568 | + break; | |
| 537 | 569 | case RTC_REG_A: |
| 570 | + ret = cmos_data[cmos_index]; | |
| 538 | 571 | /* toggle update-in-progress bit for Linux (same hack as |
| 539 | 572 | plex86) */ |
| 540 | 573 | cmos_data[RTC_REG_A] ^= 0x80; |
| 541 | 574 | break; |
| 542 | 575 | case RTC_REG_C: |
| 576 | + ret = cmos_data[cmos_index]; | |
| 543 | 577 | pic_set_irq(8, 0); |
| 544 | 578 | cmos_data[RTC_REG_C] = 0x00; |
| 545 | 579 | break; |
| 580 | + default: | |
| 581 | + ret = cmos_data[cmos_index]; | |
| 582 | + break; | |
| 546 | 583 | } |
| 547 | 584 | #ifdef DEBUG_CMOS |
| 548 | 585 | printf("cmos: read index=0x%02x val=0x%02x\n", |
| ... | ... | @@ -552,27 +589,11 @@ uint32_t cmos_ioport_read(CPUState *env, uint32_t addr) |
| 552 | 589 | } |
| 553 | 590 | } |
| 554 | 591 | |
| 555 | - | |
| 556 | -static inline int to_bcd(int a) | |
| 557 | -{ | |
| 558 | - return ((a / 10) << 4) | (a % 10); | |
| 559 | -} | |
| 560 | - | |
| 561 | 592 | void cmos_init(void) |
| 562 | 593 | { |
| 563 | - struct tm *tm; | |
| 564 | - time_t ti; | |
| 565 | 594 | int val; |
| 566 | 595 | |
| 567 | - ti = time(NULL); | |
| 568 | - tm = gmtime(&ti); | |
| 569 | - cmos_data[RTC_SECONDS] = to_bcd(tm->tm_sec); | |
| 570 | - cmos_data[RTC_MINUTES] = to_bcd(tm->tm_min); | |
| 571 | - cmos_data[RTC_HOURS] = to_bcd(tm->tm_hour); | |
| 572 | - cmos_data[RTC_DAY_OF_WEEK] = to_bcd(tm->tm_wday); | |
| 573 | - cmos_data[RTC_DAY_OF_MONTH] = to_bcd(tm->tm_mday); | |
| 574 | - cmos_data[RTC_MONTH] = to_bcd(tm->tm_mon + 1); | |
| 575 | - cmos_data[RTC_YEAR] = to_bcd(tm->tm_year % 100); | |
| 596 | + cmos_update_time(); | |
| 576 | 597 | |
| 577 | 598 | cmos_data[RTC_REG_A] = 0x26; |
| 578 | 599 | cmos_data[RTC_REG_B] = 0x02; |
| ... | ... | @@ -580,7 +601,6 @@ void cmos_init(void) |
| 580 | 601 | cmos_data[RTC_REG_D] = 0x80; |
| 581 | 602 | |
| 582 | 603 | /* various important CMOS locations needed by PC/Bochs bios */ |
| 583 | - cmos_data[REG_IBM_CENTURY_BYTE] = to_bcd((tm->tm_year / 100) + 19); | |
| 584 | 604 | |
| 585 | 605 | cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
| 586 | 606 | cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */ |
| ... | ... | @@ -676,14 +696,15 @@ typedef struct PicState { |
| 676 | 696 | uint8_t irr; /* interrupt request register */ |
| 677 | 697 | uint8_t imr; /* interrupt mask register */ |
| 678 | 698 | uint8_t isr; /* interrupt service register */ |
| 679 | - uint8_t priority_add; /* used to compute irq priority */ | |
| 699 | + uint8_t priority_add; /* highest irq priority */ | |
| 680 | 700 | uint8_t irq_base; |
| 681 | 701 | uint8_t read_reg_select; |
| 682 | 702 | uint8_t poll; |
| 683 | 703 | uint8_t special_mask; |
| 684 | 704 | uint8_t init_state; |
| 685 | 705 | uint8_t auto_eoi; |
| 686 | - uint8_t rotate_on_autoeoi; | |
| 706 | + uint8_t rotate_on_auto_eoi; | |
| 707 | + uint8_t special_fully_nested_mode; | |
| 687 | 708 | uint8_t init4; /* true if 4 byte init */ |
| 688 | 709 | } PicState; |
| 689 | 710 | |
| ... | ... | @@ -705,14 +726,16 @@ static inline void pic_set_irq1(PicState *s, int irq, int level) |
| 705 | 726 | } |
| 706 | 727 | } |
| 707 | 728 | |
| 729 | +/* return the highest priority found in mask (highest = smallest | |
| 730 | + number). Return 8 if no irq */ | |
| 708 | 731 | static inline int get_priority(PicState *s, int mask) |
| 709 | 732 | { |
| 710 | 733 | int priority; |
| 711 | 734 | if (mask == 0) |
| 712 | - return -1; | |
| 713 | - priority = 7; | |
| 735 | + return 8; | |
| 736 | + priority = 0; | |
| 714 | 737 | while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) |
| 715 | - priority--; | |
| 738 | + priority++; | |
| 716 | 739 | return priority; |
| 717 | 740 | } |
| 718 | 741 | |
| ... | ... | @@ -723,13 +746,18 @@ static int pic_get_irq(PicState *s) |
| 723 | 746 | |
| 724 | 747 | mask = s->irr & ~s->imr; |
| 725 | 748 | priority = get_priority(s, mask); |
| 726 | - if (priority < 0) | |
| 749 | + if (priority == 8) | |
| 727 | 750 | return -1; |
| 728 | - /* compute current priority */ | |
| 729 | - cur_priority = get_priority(s, s->isr); | |
| 730 | - if (priority > cur_priority) { | |
| 751 | + /* compute current priority. If special fully nested mode on the | |
| 752 | + master, the IRQ coming from the slave is not taken into account | |
| 753 | + for the priority computation. */ | |
| 754 | + mask = s->isr; | |
| 755 | + if (s->special_fully_nested_mode && s == &pics[0]) | |
| 756 | + mask &= ~(1 << 2); | |
| 757 | + cur_priority = get_priority(s, mask); | |
| 758 | + if (priority < cur_priority) { | |
| 731 | 759 | /* higher priority found: an irq should be generated */ |
| 732 | - return priority; | |
| 760 | + return (priority + s->priority_add) & 7; | |
| 733 | 761 | } else { |
| 734 | 762 | return -1; |
| 735 | 763 | } |
| ... | ... | @@ -758,6 +786,17 @@ void pic_update_irq(void) |
| 758 | 786 | /* from master pic */ |
| 759 | 787 | pic_irq_requested = irq; |
| 760 | 788 | } |
| 789 | +#if defined(DEBUG_PIC) | |
| 790 | + { | |
| 791 | + int i; | |
| 792 | + for(i = 0; i < 2; i++) { | |
| 793 | + printf("pic%d: imr=%x irr=%x padd=%d\n", | |
| 794 | + i, pics[i].imr, pics[i].irr, pics[i].priority_add); | |
| 795 | + | |
| 796 | + } | |
| 797 | + } | |
| 798 | + printf("pic: cpu_interrupt req=%d\n", pic_irq_requested); | |
| 799 | +#endif | |
| 761 | 800 | cpu_interrupt(global_env, CPU_INTERRUPT_HARD); |
| 762 | 801 | } |
| 763 | 802 | } |
| ... | ... | @@ -787,6 +826,18 @@ void pic_set_irq(int irq, int level) |
| 787 | 826 | pic_update_irq(); |
| 788 | 827 | } |
| 789 | 828 | |
| 829 | +/* acknowledge interrupt 'irq' */ | |
| 830 | +static inline void pic_intack(PicState *s, int irq) | |
| 831 | +{ | |
| 832 | + if (s->auto_eoi) { | |
| 833 | + if (s->rotate_on_auto_eoi) | |
| 834 | + s->priority_add = (irq + 1) & 7; | |
| 835 | + } else { | |
| 836 | + s->isr |= (1 << irq); | |
| 837 | + } | |
| 838 | + s->irr &= ~(1 << irq); | |
| 839 | +} | |
| 840 | + | |
| 790 | 841 | int cpu_x86_get_pic_interrupt(CPUState *env) |
| 791 | 842 | { |
| 792 | 843 | int irq, irq2, intno; |
| ... | ... | @@ -804,22 +855,20 @@ int cpu_x86_get_pic_interrupt(CPUState *env) |
| 804 | 855 | |
| 805 | 856 | if (irq >= 8) { |
| 806 | 857 | irq2 = irq & 7; |
| 807 | - pics[1].isr |= (1 << irq2); | |
| 808 | - pics[1].irr &= ~(1 << irq2); | |
| 858 | + pic_intack(&pics[1], irq2); | |
| 809 | 859 | irq = 2; |
| 810 | 860 | intno = pics[1].irq_base + irq2; |
| 811 | 861 | } else { |
| 812 | 862 | intno = pics[0].irq_base + irq; |
| 813 | 863 | } |
| 814 | - pics[0].isr |= (1 << irq); | |
| 815 | - pics[0].irr &= ~(1 << irq); | |
| 864 | + pic_intack(&pics[0], irq); | |
| 816 | 865 | return intno; |
| 817 | 866 | } |
| 818 | 867 | |
| 819 | 868 | void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) |
| 820 | 869 | { |
| 821 | 870 | PicState *s; |
| 822 | - int priority; | |
| 871 | + int priority, cmd, irq; | |
| 823 | 872 | |
| 824 | 873 | #ifdef DEBUG_PIC |
| 825 | 874 | printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); |
| ... | ... | @@ -837,45 +886,48 @@ void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) |
| 837 | 886 | if (val & 0x08) |
| 838 | 887 | hw_error("level sensitive irq not supported"); |
| 839 | 888 | } else if (val & 0x08) { |
| 840 | - if (val & 0x04) { | |
| 889 | + if (val & 0x04) | |
| 841 | 890 | s->poll = 1; |
| 842 | - } else { | |
| 843 | 891 | if (val & 0x02) |
| 844 | 892 | s->read_reg_select = val & 1; |
| 845 | 893 | if (val & 0x40) |
| 846 | 894 | s->special_mask = (val >> 5) & 1; |
| 847 | - } | |
| 848 | 895 | } else { |
| 849 | - switch(val) { | |
| 850 | - case 0x00: | |
| 851 | - case 0x80: | |
| 852 | - s->rotate_on_autoeoi = val >> 7; | |
| 896 | + cmd = val >> 5; | |
| 897 | + switch(cmd) { | |
| 898 | + case 0: | |
| 899 | + case 4: | |
| 900 | + s->rotate_on_auto_eoi = cmd >> 2; | |
| 853 | 901 | break; |
| 854 | - case 0x20: /* end of interrupt */ | |
| 855 | - case 0xa0: | |
| 902 | + case 1: /* end of interrupt */ | |
| 903 | + case 5: | |
| 856 | 904 | priority = get_priority(s, s->isr); |
| 857 | - if (priority >= 0) { | |
| 858 | - s->isr &= ~(1 << ((priority + s->priority_add) & 7)); | |
| 905 | + if (priority != 8) { | |
| 906 | + irq = (priority + s->priority_add) & 7; | |
| 907 | + s->isr &= ~(1 << irq); | |
| 908 | + if (cmd == 5) | |
| 909 | + s->priority_add = (irq + 1) & 7; | |
| 910 | + pic_update_irq(); | |
| 859 | 911 | } |
| 860 | - if (val == 0xa0) | |
| 861 | - s->priority_add = (s->priority_add + 1) & 7; | |
| 862 | - pic_update_irq(); | |
| 863 | 912 | break; |
| 864 | - case 0x60 ... 0x67: | |
| 865 | - priority = val & 7; | |
| 866 | - s->isr &= ~(1 << priority); | |
| 913 | + case 3: | |
| 914 | + irq = val & 7; | |
| 915 | + s->isr &= ~(1 << irq); | |
| 867 | 916 | pic_update_irq(); |
| 868 | 917 | break; |
| 869 | - case 0xc0 ... 0xc7: | |
| 918 | + case 6: | |
| 870 | 919 | s->priority_add = (val + 1) & 7; |
| 871 | 920 | pic_update_irq(); |
| 872 | 921 | break; |
| 873 | - case 0xe0 ... 0xe7: | |
| 874 | - priority = val & 7; | |
| 875 | - s->isr &= ~(1 << priority); | |
| 876 | - s->priority_add = (priority + 1) & 7; | |
| 922 | + case 7: | |
| 923 | + irq = val & 7; | |
| 924 | + s->isr &= ~(1 << irq); | |
| 925 | + s->priority_add = (irq + 1) & 7; | |
| 877 | 926 | pic_update_irq(); |
| 878 | 927 | break; |
| 928 | + default: | |
| 929 | + /* no operation */ | |
| 930 | + break; | |
| 879 | 931 | } |
| 880 | 932 | } |
| 881 | 933 | } else { |
| ... | ... | @@ -897,6 +949,7 @@ void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) |
| 897 | 949 | } |
| 898 | 950 | break; |
| 899 | 951 | case 3: |
| 952 | + s->special_fully_nested_mode = (val >> 4) & 1; | |
| 900 | 953 | s->auto_eoi = (val >> 1) & 1; |
| 901 | 954 | s->init_state = 0; |
| 902 | 955 | break; |
| ... | ... | @@ -935,18 +988,18 @@ uint32_t pic_ioport_read(CPUState *env, uint32_t addr1) |
| 935 | 988 | addr = addr1; |
| 936 | 989 | s = &pics[addr >> 7]; |
| 937 | 990 | addr &= 1; |
| 938 | - if (s->poll == 1) { | |
| 991 | + if (s->poll) { | |
| 939 | 992 | ret = pic_poll_read(s, addr1); |
| 940 | 993 | s->poll = 0; |
| 941 | 994 | } else { |
| 942 | - if (addr == 0) { | |
| 943 | - if (s->read_reg_select) | |
| 944 | - ret = s->isr; | |
| 945 | - else | |
| 946 | - ret = s->irr; | |
| 947 | - } else { | |
| 948 | - ret = s->imr; | |
| 949 | - } | |
| 995 | + if (addr == 0) { | |
| 996 | + if (s->read_reg_select) | |
| 997 | + ret = s->isr; | |
| 998 | + else | |
| 999 | + ret = s->irr; | |
| 1000 | + } else { | |
| 1001 | + ret = s->imr; | |
| 1002 | + } | |
| 950 | 1003 | } |
| 951 | 1004 | #ifdef DEBUG_PIC |
| 952 | 1005 | printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret); |
| ... | ... | @@ -1729,6 +1782,9 @@ void serial_received_byte(SerialState *s, int ch) |
| 1729 | 1782 | fflush(stdout); |
| 1730 | 1783 | term_command = 1; |
| 1731 | 1784 | break; |
| 1785 | + case 'd': | |
| 1786 | + cpu_set_log(CPU_LOG_ALL); | |
| 1787 | + break; | |
| 1732 | 1788 | case TERM_ESCAPE: |
| 1733 | 1789 | goto send_char; |
| 1734 | 1790 | } |
| ... | ... | @@ -3180,7 +3236,7 @@ void help(void) |
| 3180 | 3236 | "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n" |
| 3181 | 3237 | "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" |
| 3182 | 3238 | "-cdrom file use 'file' as IDE cdrom 2 image\n" |
| 3183 | - "-boot [c|d] boot on hard disk (c) or CD-ROM (d)\n" | |
| 3239 | + "-boot [a|b|c|d] boot on floppy (a, b), hard disk (c) or CD-ROM (d)\n" | |
| 3184 | 3240 | "-snapshot write to temporary files instead of disk image files\n" |
| 3185 | 3241 | "-m megs set virtual RAM size to megs MB\n" |
| 3186 | 3242 | "-n script set network init script [default=%s]\n" |
| ... | ... | @@ -3195,7 +3251,7 @@ void help(void) |
| 3195 | 3251 | "Debug/Expert options:\n" |
| 3196 | 3252 | "-s wait gdb connection to port %d\n" |
| 3197 | 3253 | "-p port change gdb connection port\n" |
| 3198 | - "-d output log in /tmp/vl.log\n" | |
| 3254 | + "-d output log to %s\n" | |
| 3199 | 3255 | "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" |
| 3200 | 3256 | "-L path set the directory for the BIOS and VGA BIOS\n" |
| 3201 | 3257 | "\n" |
| ... | ... | @@ -3206,7 +3262,8 @@ void help(void) |
| 3206 | 3262 | "qemu-fast", |
| 3207 | 3263 | #endif |
| 3208 | 3264 | DEFAULT_NETWORK_SCRIPT, |
| 3209 | - DEFAULT_GDBSTUB_PORT); | |
| 3265 | + DEFAULT_GDBSTUB_PORT, | |
| 3266 | + "/tmp/qemu.log"); | |
| 3210 | 3267 | term_print_help(); |
| 3211 | 3268 | #ifndef CONFIG_SOFTMMU |
| 3212 | 3269 | printf("\n" | ... | ... |