Revision 115646b6

b/Changelog
3 3
  - Monitor multiplexing to several I/O channels (Jason Wessel)
4 4
  - ds1225y nvram support (Herve Poussineau)
5 5
  - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
6
  - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
6
  - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif)
7 7
  - MIPS 64-bit FPU support (Thiemo Seufer)
8 8
  - Xscale PDA emulation (Andrzei Zaborowski)
9 9
  - ColdFire system emulation (Paul Brook)
b/hw/slavio_timer.c
54 54
    ptimer_state *timer;
55 55
    uint32_t count, counthigh, reached;
56 56
    uint64_t limit;
57
    int stopped;
58
    int mode; // 0 = processor, 1 = user, 2 = system
57
    // processor only
58
    int running;
59
    struct SLAVIO_TIMERState *master;
60
    int slave_index;
61
    // system only
59 62
    struct SLAVIO_TIMERState *slave[MAX_CPUS];
60 63
    uint32_t slave_mode;
61 64
} SLAVIO_TIMERState;
62 65

  
63 66
#define TIMER_MAXADDR 0x1f
64
#define TIMER_SIZE (TIMER_MAXADDR + 1)
67
#define SYS_TIMER_SIZE 0x14
65 68
#define CPU_TIMER_SIZE 0x10
66 69

  
70
static int slavio_timer_is_user(SLAVIO_TIMERState *s)
71
{
72
    return s->master && (s->master->slave_mode & (1 << s->slave_index));
73
}
74

  
67 75
// Update count, set irq, update expire_time
68 76
// Convert from ptimer countdown units
69 77
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
......
84 92

  
85 93
    slavio_timer_get_out(s);
86 94
    DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
87
    s->reached = 0x80000000;
88
    if (s->mode != 1)
95
    if (!slavio_timer_is_user(s)) {
96
        s->reached = 0x80000000;
89 97
        qemu_irq_raise(s->irq);
98
    }
90 99
}
91 100

  
92 101
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
......
99 108
    case 0:
100 109
        // read limit (system counter mode) or read most signifying
101 110
        // part of counter (user mode)
102
        if (s->mode != 1) {
111
        if (slavio_timer_is_user(s)) {
112
            // read user timer MSW
113
            slavio_timer_get_out(s);
114
            ret = s->counthigh;
115
        } else {
116
            // read limit
103 117
            // clear irq
104 118
            qemu_irq_lower(s->irq);
105 119
            s->reached = 0;
106 120
            ret = s->limit & 0x7fffffff;
107 121
        }
108
        else {
109
            slavio_timer_get_out(s);
110
            ret = s->counthigh & 0x7fffffff;
111
        }
112 122
        break;
113 123
    case 1:
114 124
        // read counter and reached bit (system mode) or read lsbits
115 125
        // of counter (user mode)
116 126
        slavio_timer_get_out(s);
117
        if (s->mode != 1)
118
            ret = (s->count & 0x7fffffff) | s->reached;
119
        else
120
            ret = s->count;
127
        if (slavio_timer_is_user(s)) // read user timer LSW
128
            ret = s->count & 0xffffffe00;
129
        else // read limit
130
            ret = (s->count & 0x7ffffe00) | s->reached;
121 131
        break;
122 132
    case 3:
133
        // only available in processor counter/timer
123 134
        // read start/stop status
124
        ret = s->stopped;
135
        ret = s->running;
125 136
        break;
126 137
    case 4:
138
        // only available in system counter
127 139
        // read user/system mode
128 140
        ret = s->slave_mode;
129 141
        break;
130 142
    default:
143
        DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
131 144
        ret = 0;
132 145
        break;
133 146
    }
......
146 159
    saddr = (addr & TIMER_MAXADDR) >> 2;
147 160
    switch (saddr) {
148 161
    case 0:
149
        if (s->mode == 1) {
150
            // set user counter limit MSW, reset counter
162
        if (slavio_timer_is_user(s)) {
163
            // set user counter MSW, reset counter
151 164
            qemu_irq_lower(s->irq);
152
            s->limit &= 0xfffffe00ULL;
153
            s->limit |= (uint64_t)val << 32;
165
            s->limit = 0x7ffffffffffffe00ULL;
166
            DPRINTF("processor %d user timer reset\n", s->slave_index);
167
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
168
        } else {
169
            // set limit, reset counter
170
            qemu_irq_lower(s->irq);
171
            s->limit = val & 0x7ffffe00ULL;
154 172
            if (!s->limit)
155
                s->limit = 0x7ffffffffffffe00ULL;
173
                s->limit = 0x7ffffe00ULL;
156 174
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
157
            break;
158 175
        }
159
        // set limit, reset counter
160
        reload = 1;
161
        qemu_irq_lower(s->irq);
162
        // fall through
176
        break;
177
    case 1:
178
        if (slavio_timer_is_user(s)) {
179
            // set user counter LSW, reset counter
180
            qemu_irq_lower(s->irq);
181
            s->limit = 0x7ffffffffffffe00ULL;
182
            DPRINTF("processor %d user timer reset\n", s->slave_index);
183
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
184
        } else
185
            DPRINTF("not user timer\n");
186
        break;
163 187
    case 2:
164 188
        // set limit without resetting counter
165 189
        s->limit = val & 0x7ffffe00ULL;
......
167 191
            s->limit = 0x7ffffe00ULL;
168 192
        ptimer_set_limit(s->timer, s->limit >> 9, reload);
169 193
        break;
170
    case 1:
171
        // set user counter limit LSW, reset counter
172
        if (s->mode == 1) {
173
            qemu_irq_lower(s->irq);
174
            s->limit &= 0x7fffffff00000000ULL;
175
            s->limit |= val & 0xfffffe00ULL;
176
            if (!s->limit)
177
                s->limit = 0x7ffffffffffffe00ULL;
178
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
179
        }
180
        break;
181 194
    case 3:
182
        // start/stop user counter
183
        if (s->mode == 1) {
184
            if (val & 1) {
185
                ptimer_stop(s->timer);
186
                s->stopped = 1;
187
            }
188
            else {
195
        if (slavio_timer_is_user(s)) {
196
            // start/stop user counter
197
            if ((val & 1) && !s->running) {
198
                DPRINTF("processor %d user timer started\n", s->slave_index);
189 199
                ptimer_run(s->timer, 0);
190
                s->stopped = 0;
200
                s->running = 1;
201
            } else if (!(val & 1) && s->running) {
202
                DPRINTF("processor %d user timer stopped\n", s->slave_index);
203
                ptimer_stop(s->timer);
204
                s->running = 0;
191 205
            }
192 206
        }
193 207
        break;
194 208
    case 4:
195
        // bit 0: user (1) or system (0) counter mode
196
        {
209
        if (s->master == NULL) {
197 210
            unsigned int i;
198 211

  
199 212
            for (i = 0; i < MAX_CPUS; i++) {
200 213
                if (val & (1 << i)) {
201 214
                    qemu_irq_lower(s->slave[i]->irq);
202 215
                    s->slave[i]->limit = -1ULL;
203
                    s->slave[i]->mode = 1;
204
                } else {
205
                    s->slave[i]->mode = 0;
206 216
                }
207
                ptimer_stop(s->slave[i]->timer);
208
                ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9,
209
                                 1);
210
                ptimer_run(s->slave[i]->timer, 0);
217
                if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
218
                    ptimer_stop(s->slave[i]->timer);
219
                    ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, 1);
220
                    DPRINTF("processor %d timer changed\n", s->slave[i]->slave_index);
221
                    ptimer_run(s->slave[i]->timer, 0);
222
                }
211 223
            }
212 224
            s->slave_mode = val & ((1 << MAX_CPUS) - 1);
213
        }
225
        } else
226
            DPRINTF("not system timer\n");
214 227
        break;
215 228
    default:
229
        DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
216 230
        break;
217 231
    }
218 232
}
......
238 252
    qemu_put_be32s(f, &s->counthigh);
239 253
    qemu_put_be32(f, 0); // Was irq
240 254
    qemu_put_be32s(f, &s->reached);
241
    qemu_put_be32s(f, &s->stopped);
242
    qemu_put_be32s(f, &s->mode);
255
    qemu_put_be32s(f, &s->running);
256
    qemu_put_be32s(f, 0); // Was mode
243 257
    qemu_put_ptimer(f, s->timer);
244 258
}
245 259

  
......
256 270
    qemu_get_be32s(f, &s->counthigh);
257 271
    qemu_get_be32s(f, &tmp); // Was irq
258 272
    qemu_get_be32s(f, &s->reached);
259
    qemu_get_be32s(f, &s->stopped);
260
    qemu_get_be32s(f, &s->mode);
273
    qemu_get_be32s(f, &s->running);
274
    qemu_get_be32s(f, &tmp); // Was mode
261 275
    qemu_get_ptimer(f, s->timer);
262 276

  
263 277
    return 0;
......
267 281
{
268 282
    SLAVIO_TIMERState *s = opaque;
269 283

  
270
    s->limit = 0x7ffffe00ULL;
284
    if (slavio_timer_is_user(s))
285
        s->limit = 0x7ffffffffffffe00ULL;
286
    else
287
        s->limit = 0x7ffffe00ULL;
271 288
    s->count = 0;
272 289
    s->reached = 0;
273
    s->mode &= 2;
274 290
    ptimer_set_limit(s->timer, s->limit >> 9, 1);
275 291
    ptimer_run(s->timer, 0);
276
    s->stopped = 1;
292
    s->running = 1;
277 293
    qemu_irq_lower(s->irq);
278 294
}
279 295

  
280 296
static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
281
                                            qemu_irq irq, int mode)
297
                                            qemu_irq irq,
298
                                            SLAVIO_TIMERState *master,
299
                                            int slave_index)
282 300
{
283 301
    int slavio_timer_io_memory;
284 302
    SLAVIO_TIMERState *s;
......
288 306
    if (!s)
289 307
        return s;
290 308
    s->irq = irq;
291
    s->mode = mode;
309
    s->master = master;
310
    s->slave_index = slave_index;
292 311
    bh = qemu_bh_new(slavio_timer_irq, s);
293 312
    s->timer = ptimer_init(bh);
294 313
    ptimer_set_period(s->timer, 500ULL);
295 314

  
296 315
    slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
297 316
                                                    slavio_timer_mem_write, s);
298
    if (mode < 2)
317
    if (master)
299 318
        cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory);
300 319
    else
301
        cpu_register_physical_memory(addr, TIMER_SIZE,
302
                                     slavio_timer_io_memory);
320
        cpu_register_physical_memory(addr, SYS_TIMER_SIZE, slavio_timer_io_memory);
303 321
    register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s);
304 322
    qemu_register_reset(slavio_timer_reset, s);
305 323
    slavio_timer_reset(s);
......
313 331
    SLAVIO_TIMERState *master;
314 332
    unsigned int i;
315 333

  
316
    master = slavio_timer_init(base + 0x10000ULL, master_irq, 2);
334
    master = slavio_timer_init(base + 0x10000ULL, master_irq, NULL, 0);
317 335

  
318 336
    for (i = 0; i < MAX_CPUS; i++) {
319 337
        master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
320 338
                                             (i * TARGET_PAGE_SIZE),
321
                                             cpu_irqs[i], 0);
339
                                             cpu_irqs[i], master, i);
322 340
    }
323 341
}

Also available in: Unified diff