/[qemu]/qemu/hw/cuda.c
ViewVC logotype

Diff of /qemu/hw/cuda.c

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

revision 1.8 by bellard, Sun Jun 5 15:24:23 2005 UTC revision 1.9 by bellard, Thu Jul 7 21:45:18 2005 UTC
# Line 23  Line 23 
23   */   */
24  #include "vl.h"  #include "vl.h"
25    
26    /* XXX: implement all timer modes */
27    
28  //#define DEBUG_CUDA  //#define DEBUG_CUDA
29  //#define DEBUG_CUDA_PACKET  //#define DEBUG_CUDA_PACKET
30    
# Line 41  Line 43 
43  #define IER_CLR         0               /* clear bits in IER */  #define IER_CLR         0               /* clear bits in IER */
44  #define SR_INT          0x04            /* Shift register full/empty */  #define SR_INT          0x04            /* Shift register full/empty */
45  #define T1_INT          0x40            /* Timer 1 interrupt */  #define T1_INT          0x40            /* Timer 1 interrupt */
46    #define T2_INT          0x20            /* Timer 2 interrupt */
47    
48  /* Bits in ACR */  /* Bits in ACR */
49  #define T1MODE          0xc0            /* Timer 1 mode */  #define T1MODE          0xc0            /* Timer 1 mode */
# Line 91  Line 94 
94  #define RTC_OFFSET                      2082844800  #define RTC_OFFSET                      2082844800
95    
96  typedef struct CUDATimer {  typedef struct CUDATimer {
97      unsigned int latch;      int index;
98        uint16_t latch;
99      uint16_t counter_value; /* counter value at load time */      uint16_t counter_value; /* counter value at load time */
100      int64_t load_time;      int64_t load_time;
101      int64_t next_irq_time;      int64_t next_irq_time;
# Line 154  static unsigned int get_counter(CUDATime Line 158  static unsigned int get_counter(CUDATime
158    
159      d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,      d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
160                   CUDA_TIMER_FREQ, ticks_per_sec);                   CUDA_TIMER_FREQ, ticks_per_sec);
161      if (d <= s->counter_value) {      if (s->index == 0) {
162          counter = d;          /* the timer goes down from latch to -1 (period of latch + 2) */
163            if (d <= (s->counter_value + 1)) {
164                counter = (s->counter_value - d) & 0xffff;
165            } else {
166                counter = (d - (s->counter_value + 1)) % (s->latch + 2);
167                counter = (s->latch - counter) & 0xffff;
168            }
169      } else {      } else {
170          counter = s->latch - 1 - ((d - s->counter_value) % s->latch);          counter = (s->counter_value - d) & 0xffff;
171      }      }
172      return counter;      return counter;
173  }  }
# Line 175  static void set_counter(CUDAState *s, CU Line 185  static void set_counter(CUDAState *s, CU
185    
186  static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)  static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
187  {  {
188      int64_t d, next_time, base;      int64_t d, next_time;
189        unsigned int counter;
190    
191      /* current counter value */      /* current counter value */
192      d = muldiv64(current_time - s->load_time,      d = muldiv64(current_time - s->load_time,
193                   CUDA_TIMER_FREQ, ticks_per_sec);                   CUDA_TIMER_FREQ, ticks_per_sec);
194      if (d < s->counter_value) {      /* the timer goes down from latch to -1 (period of latch + 2) */
195          next_time = s->counter_value + 1;      if (d <= (s->counter_value + 1)) {
196      } else          counter = (s->counter_value - d) & 0xffff;
197      {      } else {
198          base = ((d - s->counter_value + 1) / s->latch);          counter = (d - (s->counter_value + 1)) % (s->latch + 2);
199          base = (base * s->latch) + s->counter_value;          counter = (s->latch - counter) & 0xffff;
200          next_time = base + s->latch;      }
201        
202        /* Note: we consider the irq is raised on 0 */
203        if (counter == 0xffff) {
204            next_time = d + s->latch + 1;
205        } else if (counter == 0) {
206            next_time = d + s->latch + 2;
207        } else {
208            next_time = d + counter;
209      }      }
210  #if 0  #if 0
211  #ifdef DEBUG_CUDA  #ifdef DEBUG_CUDA
# Line 249  static uint32_t cuda_readb(void *opaque, Line 269  static uint32_t cuda_readb(void *opaque,
269          break;          break;
270      case 5:      case 5:
271          val = get_counter(&s->timers[0]) >> 8;          val = get_counter(&s->timers[0]) >> 8;
         s->ifr &= ~T1_INT;  
272          cuda_update_irq(s);          cuda_update_irq(s);
273          break;          break;
274      case 6:      case 6:
275          val = s->timers[0].latch & 0xff;          val = s->timers[0].latch & 0xff;
276          break;          break;
277      case 7:      case 7:
278            /* XXX: check this */
279          val = (s->timers[0].latch >> 8) & 0xff;          val = (s->timers[0].latch >> 8) & 0xff;
280          break;          break;
281      case 8:      case 8:
282          val = get_counter(&s->timers[1]) & 0xff;          val = get_counter(&s->timers[1]) & 0xff;
283            s->ifr &= ~T2_INT;
284          break;          break;
285      case 9:      case 9:
286          val = get_counter(&s->timers[1]) >> 8;          val = get_counter(&s->timers[1]) >> 8;
# Line 317  static void cuda_writeb(void *opaque, ta Line 338  static void cuda_writeb(void *opaque, ta
338          s->dira = val;          s->dira = val;
339          break;          break;
340      case 4:      case 4:
341          val = val | (get_counter(&s->timers[0]) & 0xff00);          s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
342          set_counter(s, &s->timers[0], val);          cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
343          break;          break;
344      case 5:      case 5:
345          val = (val << 8) |  (get_counter(&s->timers[0]) & 0xff);          s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
346          set_counter(s, &s->timers[0], val);          s->ifr &= ~T1_INT;
347            set_counter(s, &s->timers[0], s->timers[0].latch);
348          break;          break;
349      case 6:      case 6:
350          s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;          s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
# Line 330  static void cuda_writeb(void *opaque, ta Line 352  static void cuda_writeb(void *opaque, ta
352          break;          break;
353      case 7:      case 7:
354          s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);          s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
355            s->ifr &= ~T1_INT;
356          cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));          cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
357          break;          break;
358      case 8:      case 8:
359          val = val | (get_counter(&s->timers[1]) & 0xff00);          s->timers[1].latch = val;
360          set_counter(s, &s->timers[1], val);          set_counter(s, &s->timers[1], val);
361          break;          break;
362      case 9:      case 9:
363          val = (val << 8) |  (get_counter(&s->timers[1]) & 0xff);          set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
         set_counter(s, &s->timers[1], val);  
364          break;          break;
365      case 10:      case 10:
366          s->sr = val;          s->sr = val;
# Line 620  int cuda_init(SetIRQFunc *set_irq, void Line 642  int cuda_init(SetIRQFunc *set_irq, void
642      s->irq_opaque = irq_opaque;      s->irq_opaque = irq_opaque;
643      s->irq = irq;      s->irq = irq;
644    
645        s->timers[0].index = 0;
646      s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);      s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
647      s->timers[0].latch = 0x10000;      s->timers[0].latch = 0xffff;
648      set_counter(s, &s->timers[0], 0xffff);      set_counter(s, &s->timers[0], 0xffff);
649      s->timers[1].latch = 0x10000;  
650        s->timers[1].index = 1;
651        s->timers[1].latch = 0;
652      //    s->ier = T1_INT | SR_INT;      //    s->ier = T1_INT | SR_INT;
653      s->ier = 0;      s->ier = 0;
654      set_counter(s, &s->timers[1], 0xffff);      set_counter(s, &s->timers[1], 0xffff);

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9

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