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" | ... | ... |