~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/slavio_timer.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-22 10:13:17 UTC
  • mfrom: (1.2.1 upstream) (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090322101317-iigjtnu5qil35dtb
Tags: 0.10.1-1
[ Aurelien Jarno ]
* New upstream stable release:
  - patches/80_stable-branch.patch: remove.
* debian/control: 
  - Remove depends on proll.
  - Move depends on device-tree-compiler to build-depends.
  - Bump Standards-Version to 3.8.1 (no changes).
* patches/82_qemu-img_decimal.patch: new patch from upstream to make
  qemu-img accept sizes with decimal values (closes: bug#501400).

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#define DPRINTF(fmt, args...) \
32
32
do { printf("TIMER: " fmt , ##args); } while (0)
33
33
#else
34
 
#define DPRINTF(fmt, args...)
 
34
#define DPRINTF(fmt, args...) do {} while (0)
35
35
#endif
36
36
 
37
37
/*
57
57
    uint32_t count, counthigh, reached;
58
58
    uint64_t limit;
59
59
    // processor only
60
 
    int running;
 
60
    uint32_t running;
61
61
    struct SLAVIO_TIMERState *master;
62
 
    int slave_index;
 
62
    uint32_t slave_index;
63
63
    // system only
64
 
    unsigned int num_slaves;
 
64
    uint32_t num_slaves;
65
65
    struct SLAVIO_TIMERState *slave[MAX_CPUS];
66
66
    uint32_t slave_mode;
67
67
} SLAVIO_TIMERState;
68
68
 
69
 
#define TIMER_MAXADDR 0x1f
70
69
#define SYS_TIMER_SIZE 0x14
71
70
#define CPU_TIMER_SIZE 0x10
72
71
 
122
121
 
123
122
    slavio_timer_get_out(s);
124
123
    DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
125
 
    if (!slavio_timer_is_user(s)) {
126
 
        s->reached = TIMER_REACHED;
 
124
    s->reached = TIMER_REACHED;
 
125
    if (!slavio_timer_is_user(s))
127
126
        qemu_irq_raise(s->irq);
128
 
    }
129
127
}
130
128
 
131
129
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
133
131
    SLAVIO_TIMERState *s = opaque;
134
132
    uint32_t saddr, ret;
135
133
 
136
 
    saddr = (addr & TIMER_MAXADDR) >> 2;
 
134
    saddr = addr >> 2;
137
135
    switch (saddr) {
138
136
    case TIMER_LIMIT:
139
137
        // read limit (system counter mode) or read most signifying
141
139
        if (slavio_timer_is_user(s)) {
142
140
            // read user timer MSW
143
141
            slavio_timer_get_out(s);
144
 
            ret = s->counthigh;
 
142
            ret = s->counthigh | s->reached;
145
143
        } else {
146
144
            // read limit
147
145
            // clear irq
155
153
        // of counter (user mode)
156
154
        slavio_timer_get_out(s);
157
155
        if (slavio_timer_is_user(s)) // read user timer LSW
158
 
            ret = s->count & TIMER_COUNT_MASK32;
 
156
            ret = s->count & TIMER_MAX_COUNT64;
159
157
        else // read limit
160
158
            ret = (s->count & TIMER_MAX_COUNT32) | s->reached;
161
159
        break;
186
184
    uint32_t saddr;
187
185
 
188
186
    DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
189
 
    saddr = (addr & TIMER_MAXADDR) >> 2;
 
187
    saddr = addr >> 2;
190
188
    switch (saddr) {
191
189
    case TIMER_LIMIT:
192
190
        if (slavio_timer_is_user(s)) {
 
191
            uint64_t count;
 
192
 
193
193
            // set user counter MSW, reset counter
194
 
            qemu_irq_lower(s->irq);
195
194
            s->limit = TIMER_MAX_COUNT64;
196
 
            DPRINTF("processor %d user timer reset\n", s->slave_index);
 
195
            s->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
 
196
            s->reached = 0;
 
197
            count = ((uint64_t)s->counthigh << 32) | s->count;
 
198
            DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
 
199
                    count);
197
200
            if (s->timer)
198
 
                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
 
201
                ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
199
202
        } else {
200
203
            // set limit, reset counter
201
204
            qemu_irq_lower(s->irq);
202
205
            s->limit = val & TIMER_MAX_COUNT32;
203
206
            if (s->timer) {
204
207
                if (s->limit == 0) /* free-run */
205
 
                    ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
 
208
                    ptimer_set_limit(s->timer,
 
209
                                     LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
206
210
                else
207
211
                    ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
208
212
            }
210
214
        break;
211
215
    case TIMER_COUNTER:
212
216
        if (slavio_timer_is_user(s)) {
 
217
            uint64_t count;
 
218
 
213
219
            // set user counter LSW, reset counter
214
 
            qemu_irq_lower(s->irq);
215
220
            s->limit = TIMER_MAX_COUNT64;
216
 
            DPRINTF("processor %d user timer reset\n", s->slave_index);
 
221
            s->count = val & TIMER_MAX_COUNT64;
 
222
            s->reached = 0;
 
223
            count = ((uint64_t)s->counthigh) << 32 | s->count;
 
224
            DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
 
225
                    count);
217
226
            if (s->timer)
218
 
                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
 
227
                ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
219
228
        } else
220
229
            DPRINTF("not user timer\n");
221
230
        break;
224
233
        s->limit = val & TIMER_MAX_COUNT32;
225
234
        if (s->timer) {
226
235
            if (s->limit == 0)  /* free-run */
227
 
                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
 
236
                ptimer_set_limit(s->timer,
 
237
                                 LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
228
238
            else
229
239
                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
230
240
        }
250
260
            unsigned int i;
251
261
 
252
262
            for (i = 0; i < s->num_slaves; i++) {
253
 
                if (val & (1 << i)) {
254
 
                    qemu_irq_lower(s->slave[i]->irq);
255
 
                    s->slave[i]->limit = -1ULL;
256
 
                } else {
257
 
                    ptimer_stop(s->slave[i]->timer);
258
 
                }
259
 
                if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
260
 
                    ptimer_stop(s->slave[i]->timer);
261
 
                    ptimer_set_limit(s->slave[i]->timer,
262
 
                                     LIMIT_TO_PERIODS(s->slave[i]->limit), 1);
263
 
                    DPRINTF("processor %d timer changed\n",
264
 
                            s->slave[i]->slave_index);
265
 
                    ptimer_run(s->slave[i]->timer, 0);
 
263
                unsigned int processor = 1 << i;
 
264
 
 
265
                // check for a change in timer mode for this processor
 
266
                if ((val & processor) != (s->slave_mode & processor)) {
 
267
                    if (val & processor) { // counter -> user timer
 
268
                        qemu_irq_lower(s->slave[i]->irq);
 
269
                        // counters are always running
 
270
                        ptimer_stop(s->slave[i]->timer);
 
271
                        s->slave[i]->running = 0;
 
272
                        // user timer limit is always the same
 
273
                        s->slave[i]->limit = TIMER_MAX_COUNT64;
 
274
                        ptimer_set_limit(s->slave[i]->timer,
 
275
                                         LIMIT_TO_PERIODS(s->slave[i]->limit),
 
276
                                         1);
 
277
                        // set this processors user timer bit in config
 
278
                        // register
 
279
                        s->slave_mode |= processor;
 
280
                        DPRINTF("processor %d changed from counter to user "
 
281
                                "timer\n", s->slave[i]->slave_index);
 
282
                    } else { // user timer -> counter
 
283
                        // stop the user timer if it is running
 
284
                        if (s->slave[i]->running)
 
285
                            ptimer_stop(s->slave[i]->timer);
 
286
                        // start the counter
 
287
                        ptimer_run(s->slave[i]->timer, 0);
 
288
                        s->slave[i]->running = 1;
 
289
                        // clear this processors user timer bit in config
 
290
                        // register
 
291
                        s->slave_mode &= ~processor;
 
292
                        DPRINTF("processor %d changed from user timer to "
 
293
                                "counter\n", s->slave[i]->slave_index);
 
294
                    }
266
295
                }
267
296
            }
268
 
            s->slave_mode = val & ((1 << s->num_slaves) - 1);
269
297
        } else
270
298
            DPRINTF("not system timer\n");
271
299
        break;
337
365
static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
338
366
                                            qemu_irq irq,
339
367
                                            SLAVIO_TIMERState *master,
340
 
                                            int slave_index)
 
368
                                            uint32_t slave_index)
341
369
{
342
370
    int slavio_timer_io_memory;
343
371
    SLAVIO_TIMERState *s;
344
372
    QEMUBH *bh;
345
373
 
346
374
    s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
347
 
    if (!s)
348
 
        return s;
349
375
    s->irq = irq;
350
376
    s->master = master;
351
377
    s->slave_index = slave_index;