/[qemu]/qemu/vl.c
ViewVC logotype

Diff of /qemu/vl.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by bellard, Wed Jun 25 16:20:35 2003 UTC revision 1.4 by bellard, Fri Jun 27 12:01:39 2003 UTC
# Line 745  void pic_init(void) Line 745  void pic_init(void)
745  #define RW_STATE_LATCHED_WORD1 5  #define RW_STATE_LATCHED_WORD1 5
746    
747  typedef struct PITChannelState {  typedef struct PITChannelState {
748      uint16_t count;      int count; /* can be 65536 */
749      uint16_t latched_count;      uint16_t latched_count;
750      uint8_t rw_state;      uint8_t rw_state;
751      uint8_t mode;      uint8_t mode;
752      uint8_t bcd; /* not supported */      uint8_t bcd; /* not supported */
753      uint8_t gate; /* timer start */      uint8_t gate; /* timer start */
754      int64_t count_load_time;      int64_t count_load_time;
755        int64_t count_last_edge_check_time;
756  } PITChannelState;  } PITChannelState;
757    
758  PITChannelState pit_channels[3];  PITChannelState pit_channels[3];
759  int speaker_data_on;  int speaker_data_on;
760    int pit_min_timer_count = 0;
761    
762  int64_t ticks_per_sec;  int64_t ticks_per_sec;
763    
# Line 785  void cpu_calibrate_ticks(void) Line 787  void cpu_calibrate_ticks(void)
787      ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;      ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
788  }  }
789    
790    /* compute with 96 bit intermediate result: (a*b)/c */
791    static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
792    {
793        union {
794            uint64_t ll;
795            struct {
796    #ifdef WORDS_BIGENDIAN
797                uint32_t high, low;
798    #else
799                uint32_t low, high;
800    #endif            
801            } l;
802        } u, res;
803        uint64_t rl, rh;
804    
805        u.ll = a;
806        rl = (uint64_t)u.l.low * (uint64_t)b;
807        rh = (uint64_t)u.l.high * (uint64_t)b;
808        rh += (rl >> 32);
809        res.l.high = rh / c;
810        res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
811        return res.ll;
812    }
813    
814  static int pit_get_count(PITChannelState *s)  static int pit_get_count(PITChannelState *s)
815  {  {
816      int64_t d;      uint64_t d;
817      int counter;      int counter;
818    
819      d = ((cpu_get_ticks() - s->count_load_time) * PIT_FREQ) /      d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
         ticks_per_sec;  
820      switch(s->mode) {      switch(s->mode) {
821      case 0:      case 0:
822      case 1:      case 1:
# Line 809  static int pit_get_count(PITChannelState Line 834  static int pit_get_count(PITChannelState
834  /* get pit output bit */  /* get pit output bit */
835  static int pit_get_out(PITChannelState *s)  static int pit_get_out(PITChannelState *s)
836  {  {
837      int64_t d;      uint64_t d;
838      int out;      int out;
839    
840      d = ((cpu_get_ticks() - s->count_load_time) * PIT_FREQ) /      d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
         ticks_per_sec;  
841      switch(s->mode) {      switch(s->mode) {
842      default:      default:
843      case 0:      case 0:
# Line 839  static int pit_get_out(PITChannelState * Line 863  static int pit_get_out(PITChannelState *
863      return out;      return out;
864  }  }
865    
866    /* get the number of 0 to 1 transitions we had since we call this
867       function */
868    /* XXX: maybe better to use ticks precision to avoid getting edges
869       twice if checks are done at very small intervals */
870    static int pit_get_out_edges(PITChannelState *s)
871    {
872        uint64_t d1, d2;
873        int64_t ticks;
874        int ret, v;
875    
876        ticks = cpu_get_ticks();
877        d1 = muldiv64(s->count_last_edge_check_time - s->count_load_time,
878                     PIT_FREQ, ticks_per_sec);
879        d2 = muldiv64(ticks - s->count_load_time,
880                      PIT_FREQ, ticks_per_sec);
881        s->count_last_edge_check_time = ticks;
882        switch(s->mode) {
883        default:
884        case 0:
885            if (d1 < s->count && d2 >= s->count)
886                ret = 1;
887            else
888                ret = 0;
889            break;
890        case 1:
891            ret = 0;
892            break;
893        case 2:
894            d1 /= s->count;
895            d2 /= s->count;
896            ret = d2 - d1;
897            break;
898        case 3:
899            v = s->count - (s->count >> 1);
900            d1 = (d1 + v) / s->count;
901            d2 = (d2 + v) / s->count;
902            ret = d2 - d1;
903            break;
904        case 4:
905        case 5:
906            if (d1 < s->count && d2 >= s->count)
907                ret = 1;
908            else
909                ret = 0;
910            break;
911        }
912        return ret;
913    }
914    
915    static inline void pit_load_count(PITChannelState *s, int val)
916    {
917        if (val == 0)
918            val = 0x10000;
919        s->count_load_time = cpu_get_ticks();
920        s->count_last_edge_check_time = s->count_load_time;
921        s->count = val;
922        if (s == &pit_channels[0] && val <= pit_min_timer_count) {
923            fprintf(stderr,
924                    "\nWARNING: vl: on your system, accurate timer emulation is impossible if its frequency is more than %d Hz. If using a 2.5.xx Linux kernel, you must patch asm/param.h to change HZ from 1000 to 100.\n\n",
925                    PIT_FREQ / pit_min_timer_count);
926        }
927    }
928    
929  void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)  void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
930  {  {
931      int channel, access;      int channel, access;
932      PITChannelState *s;      PITChannelState *s;
933        
934      addr &= 3;      addr &= 3;
935      if (addr == 3) {      if (addr == 3) {
936          channel = val >> 6;          channel = val >> 6;
# Line 857  void pit_ioport_write(CPUX86State *env, Line 944  void pit_ioport_write(CPUX86State *env,
944              s->rw_state = RW_STATE_LATCHED_WORD0;              s->rw_state = RW_STATE_LATCHED_WORD0;
945              break;              break;
946          default:          default:
947                s->mode = (val >> 1) & 7;
948                s->bcd = val & 1;
949              s->rw_state = access - 1 +  RW_STATE_LSB;              s->rw_state = access - 1 +  RW_STATE_LSB;
950              break;              break;
951          }          }
         s->mode = (val >> 1) & 7;  
         s->bcd = val & 1;  
952      } else {      } else {
953          s = &pit_channels[addr];          s = &pit_channels[addr];
954          switch(s->rw_state) {          switch(s->rw_state) {
955          case RW_STATE_LSB:          case RW_STATE_LSB:
956              s->count_load_time = cpu_get_ticks();              pit_load_count(s, val);
             s->count = val;  
957              break;              break;
958          case RW_STATE_MSB:          case RW_STATE_MSB:
959              s->count_load_time = cpu_get_ticks();              pit_load_count(s, val << 8);
             s->count = (val << 8);  
960              break;              break;
961          case RW_STATE_WORD0:          case RW_STATE_WORD0:
962          case RW_STATE_WORD1:          case RW_STATE_WORD1:
963              if (s->rw_state & 1) {              if (s->rw_state & 1) {
964                  s->count_load_time = cpu_get_ticks();                  pit_load_count(s, (s->latched_count & 0xff) | (val << 8));
                 s->count = (s->latched_count & 0xff) | (val << 8);  
965              } else {              } else {
966                  s->latched_count = val;                  s->latched_count = val;
967              }              }
# Line 935  uint32_t speaker_ioport_read(CPUX86State Line 1019  uint32_t speaker_ioport_read(CPUX86State
1019    
1020  void pit_init(void)  void pit_init(void)
1021  {  {
1022      pit_channels[0].gate = 1;      PITChannelState *s;
1023      pit_channels[1].gate = 1;      int i;
1024      pit_channels[2].gate = 0;  
1025            cpu_calibrate_ticks();
1026    
1027        for(i = 0;i < 3; i++) {
1028            s = &pit_channels[i];
1029            s->mode = 3;
1030            s->gate = (i != 2);
1031            pit_load_count(s, 0);
1032        }
1033    
1034      register_ioport_writeb(0x40, 4, pit_ioport_write);      register_ioport_writeb(0x40, 4, pit_ioport_write);
1035      register_ioport_readb(0x40, 3, pit_ioport_read);      register_ioport_readb(0x40, 3, pit_ioport_read);
1036    
1037      register_ioport_readb(0x61, 1, speaker_ioport_read);      register_ioport_readb(0x61, 1, speaker_ioport_read);
1038      register_ioport_writeb(0x61, 1, speaker_ioport_write);      register_ioport_writeb(0x61, 1, speaker_ioport_write);
     cpu_calibrate_ticks();  
1039  }  }
1040    
1041  /***********************************************************/  /***********************************************************/
# Line 1462  void ne2000_ioport_write(CPUX86State *en Line 1553  void ne2000_ioport_write(CPUX86State *en
1553                  s->rcnt == 0) {                  s->rcnt == 0) {
1554                  s->isr |= ENISR_RDC;                  s->isr |= ENISR_RDC;
1555                  ne2000_update_irq(s);                  ne2000_update_irq(s);
1556                    /* XXX: find a better solution for irqs */
1557                    cpu_x86_interrupt(global_env);
1558              }              }
1559              if (val & E8390_TRANS) {              if (val & E8390_TRANS) {
1560                  net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);                  net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
# Line 1671  static void host_segv_handler(int host_s Line 1764  static void host_segv_handler(int host_s
1764  }  }
1765    
1766  static int timer_irq_pending;  static int timer_irq_pending;
1767    static int timer_irq_count;
1768    
1769  static void host_alarm_handler(int host_signum, siginfo_t *info,  static void host_alarm_handler(int host_signum, siginfo_t *info,
1770                                 void *puc)                                 void *puc)
1771  {  {
1772      /* just exit from the cpu to have a chance to handle timers */      /* NOTE: since usually the OS asks a 100 Hz clock, there can be
1773      cpu_x86_interrupt(global_env);         some drift between cpu_get_ticks() and the interrupt time. So
1774      timer_irq_pending = 1;         we queue some interrupts to avoid missing some */
1775        timer_irq_count += pit_get_out_edges(&pit_channels[0]);
1776        if (timer_irq_count) {
1777            if (timer_irq_count > 2)
1778                timer_irq_count = 2;
1779            timer_irq_count--;
1780            /* just exit from the cpu to have a chance to handle timers */
1781            cpu_x86_interrupt(global_env);
1782            timer_irq_pending = 1;
1783        }
1784  }  }
1785    
1786  void help(void)  void help(void)
# Line 1705  int main(int argc, char **argv) Line 1808  int main(int argc, char **argv)
1808      struct sigaction act;      struct sigaction act;
1809      struct itimerval itv;      struct itimerval itv;
1810      CPUX86State *env;      CPUX86State *env;
1811        const char *tmpdir;
1812        
1813      /* we never want that malloc() uses mmap() */      /* we never want that malloc() uses mmap() */
1814      mallopt(M_MMAP_THRESHOLD, 4096 * 1024);      mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
1815            
# Line 1749  int main(int argc, char **argv) Line 1853  int main(int argc, char **argv)
1853      net_init();      net_init();
1854    
1855      /* init the memory */      /* init the memory */
1856      strcpy(phys_ram_file, "/tmp/vlXXXXXX");      tmpdir = getenv("VLTMPDIR");
1857        if (!tmpdir)
1858            tmpdir = "/tmp";
1859        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);
1860      if (mkstemp(phys_ram_file) < 0) {      if (mkstemp(phys_ram_file) < 0) {
1861          fprintf(stderr, "Could not create temporary memory file\n");          fprintf(stderr, "Could not create temporary memory file '%s'\n",
1862                    phys_ram_file);
1863          exit(1);          exit(1);
1864      }      }
1865      phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);      phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
1866      if (phys_ram_fd < 0) {      if (phys_ram_fd < 0) {
1867          fprintf(stderr, "Could not open temporary memory file\n");          fprintf(stderr, "Could not open temporary memory file '%s'\n",
1868                    phys_ram_file);
1869          exit(1);          exit(1);
1870      }      }
1871      ftruncate(phys_ram_fd, phys_ram_size);      ftruncate(phys_ram_fd, phys_ram_size);
# Line 1856  int main(int argc, char **argv) Line 1965  int main(int argc, char **argv)
1965      env->eflags = 0x2;      env->eflags = 0x2;
1966    
1967      itv.it_interval.tv_sec = 0;      itv.it_interval.tv_sec = 0;
1968      itv.it_interval.tv_usec = 10 * 1000;      itv.it_interval.tv_usec = 1000;
1969      itv.it_value.tv_sec = 0;      itv.it_value.tv_sec = 0;
1970      itv.it_value.tv_usec = 10 * 1000;      itv.it_value.tv_usec = 10 * 1000;
1971      setitimer(ITIMER_REAL, &itv, NULL);      setitimer(ITIMER_REAL, &itv, NULL);
1972        /* we probe the tick duration of the kernel to inform the user if
1973           the emulated kernel requested a too high timer frequency */
1974        getitimer(ITIMER_REAL, &itv);
1975        pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) /
1976            1000000;
1977    
1978      for(;;) {      for(;;) {
1979          struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd;          struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd;

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26