Revision 5ef98b47

b/hw/etraxfs.c
30 30
#include "devices.h"
31 31
#include "boards.h"
32 32

  
33
#include "etraxfs_dma.h"
34

  
35
/* Init functions for different blocks.  */
36
extern qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base);
37
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
38
                        target_phys_addr_t base);
39
void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
40
                       qemu_irq *irq, target_phys_addr_t base);
41
void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
42
                      target_phys_addr_t base);
33
#include "etraxfs.h"
43 34

  
44 35
#define FLASH_SIZE 0x2000000
45 36
#define INTMEM_SIZE (128 * 1024)
......
62 53
                       const char *initrd_filename, const char *cpu_model)
63 54
{
64 55
    CPUState *env;
65
    qemu_irq *pic;
56
    struct etraxfs_pic *pic;
66 57
    void *etraxfs_dmac;
67 58
    struct etraxfs_dma_client *eth[2] = {NULL, NULL};
68 59
    int kernel_size;
......
110 101
    etraxfs_dmac = etraxfs_dmac_init(env, 0xb0000000, 10);
111 102
    for (i = 0; i < 10; i++) {
112 103
        /* On ETRAX, odd numbered channels are inputs.  */
113
        etraxfs_dmac_connect(etraxfs_dmac, i, pic + 7 + i, i & 1);
104
        etraxfs_dmac_connect(etraxfs_dmac, i, pic->irq + 7 + i, i & 1);
114 105
    }
115 106

  
116 107
    /* Add the two ethernet blocks.  */
117
    eth[0] = etraxfs_eth_init(&nd_table[0], env, pic + 25, 0xb0034000);
108
    eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0xb0034000);
118 109
    if (nb_nics > 1)
119
        eth[1] = etraxfs_eth_init(&nd_table[1], env, pic + 26, 0xb0036000);
110
        eth[1] = etraxfs_eth_init(&nd_table[1], env, pic->irq + 26, 0xb0036000);
120 111

  
121 112
    /* The DMA Connector block is missing, hardwire things for now.  */
122 113
    etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
......
127 118
    }
128 119

  
129 120
    /* 2 timers.  */
130
    etraxfs_timer_init(env, pic + 0x1b, 0xb001e000);
131
    etraxfs_timer_init(env, pic + 0x1b, 0xb005e000);
121
    etraxfs_timer_init(env, pic->irq + 0x1b, pic->nmi + 1, 0xb001e000);
122
    etraxfs_timer_init(env, pic->irq + 0x1b, pic->nmi + 1, 0xb005e000);
132 123

  
133 124
    for (i = 0; i < 4; i++) {
134 125
        if (serial_hds[i]) {
135
            etraxfs_ser_init(env, pic + 0x14 + i,
126
            etraxfs_ser_init(env, pic->irq + 0x14 + i,
136 127
                             serial_hds[i], 0xb0026000 + i * 0x2000);
137 128
        }
138 129
    }
b/hw/etraxfs.h
1
/*
2
 * QEMU ETRAX System Emulator
3
 *
4
 * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

  
25
#include "etraxfs_dma.h"
26

  
27
struct etraxfs_pic
28
{
29
    qemu_irq *irq;
30
    qemu_irq *nmi;
31
    qemu_irq *guru;
32

  
33
    void *internal;
34
};
35

  
36
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base);
37
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi,
38
                        target_phys_addr_t base);
39
void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
40
                       qemu_irq *irq, target_phys_addr_t base);
41
void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
42
                      target_phys_addr_t base);
b/hw/etraxfs_pic.c
24 24

  
25 25
#include <stdio.h>
26 26
#include "hw.h"
27
#include "etraxfs.h"
27 28

  
28 29
#define D(x)
29 30

  
......
143 144
{
144 145
}
145 146

  
146
static void etraxfs_pic_handler(void *opaque, int irq, int level)
147
static void irq_handler(void *opaque, int irq, int level)
147 148
{	
148 149
	struct fs_pic_state_t *fs = (void *)opaque;
149 150
	CPUState *env = fs->env;
......
187 188
	}
188 189
}
189 190

  
190
qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
191
static void nmi_handler(void *opaque, int irq, int level)
192
{	
193
	struct fs_pic_state_t *fs = (void *)opaque;
194
	CPUState *env = fs->env;
195
	uint32_t mask;
196

  
197
	mask = 1 << irq;
198
	if (level)
199
		fs->r_nmi |= mask;
200
	else
201
		fs->r_nmi &= ~mask;
202

  
203
	if (fs->r_nmi)
204
		cpu_interrupt(env, CPU_INTERRUPT_NMI);
205
	else
206
		cpu_reset_interrupt(env, CPU_INTERRUPT_NMI);
207
}
208

  
209
static void guru_handler(void *opaque, int irq, int level)
210
{	
211
	struct fs_pic_state_t *fs = (void *)opaque;
212
	CPUState *env = fs->env;
213
	cpu_abort(env, "%s unsupported exception\n", __func__);
214

  
215
}
216

  
217

  
218
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
191 219
{
192
	struct fs_pic_state_t *fs;
193
	qemu_irq *pic;
220
	struct fs_pic_state_t *fs = NULL;
221
	struct etraxfs_pic *pic = NULL;
194 222
	int intr_vect_regs;
195 223

  
196
	fs = qemu_mallocz(sizeof *fs);
197
	if (!fs)
198
		return NULL;
199
	fs->env = env;
224
	pic = qemu_mallocz(sizeof *pic);
225
	pic->internal = fs = qemu_mallocz(sizeof *fs);
226
	if (!fs || !pic)
227
		goto err;
200 228

  
201
	pic = qemu_allocate_irqs(etraxfs_pic_handler, fs, 30);
229
	fs->env = env;
230
	pic->irq = qemu_allocate_irqs(irq_handler, fs, 30);
231
	pic->nmi = qemu_allocate_irqs(nmi_handler, fs, 2);
232
	pic->guru = qemu_allocate_irqs(guru_handler, fs, 1);
202 233

  
203 234
	intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs);
204 235
	cpu_register_physical_memory(base, 0x14, intr_vect_regs);
205 236
	fs->base = base;
206 237

  
207 238
	return pic;
239
  err:
240
	free(pic);
241
	free(fs);
242
	return NULL;
208 243
}
b/hw/etraxfs_timer.c
46 46
struct fs_timer_t {
47 47
	CPUState *env;
48 48
	qemu_irq *irq;
49
	qemu_irq *nmi;
49 50
	target_phys_addr_t base;
50 51

  
51 52
	QEMUBH *bh_t0;
......
56 57
	ptimer_state *ptimer_wd;
57 58
	struct timeval last;
58 59

  
60
	int wd_hits;
61

  
59 62
	/* Control registers.  */
60 63
	uint32_t rw_tmr0_div;
61 64
	uint32_t r_tmr0_data;
......
129 132
	unsigned int freq_hz;
130 133
	unsigned int div;
131 134
	uint32_t ctrl;
135

  
132 136
	ptimer_state *timer;
133 137

  
134 138
	if (tnum == 0) {
......
163 167

  
164 168
	D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
165 169
	div = div * TIMER_SLOWDOWN;
166
	div >>= 15;
167
	freq_hz >>= 15;
170
	div >>= 10;
171
	freq_hz >>= 10;
168 172
	ptimer_set_freq(timer, freq_hz);
169 173
	ptimer_set_limit(timer, div, 0);
170 174

  
......
216 220

  
217 221
static void watchdog_hit(void *opaque)
218 222
{
219
	qemu_system_reset_request();
223
	struct fs_timer_t *t = opaque;
224
	if (t->wd_hits == 0) {
225
		/* real hw gives a single tick before reseting but we are
226
		   a bit friendlier to compensate for our slower execution.  */
227
		ptimer_set_count(t->ptimer_wd, 10);
228
		ptimer_run(t->ptimer_wd, 1);
229
		qemu_irq_raise(t->nmi[0]);
230
	}
231
	else
232
		qemu_system_reset_request();
233

  
234
	t->wd_hits++;
220 235
}
221 236

  
222 237
static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value)
......
237 252
	D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", 
238 253
		 wd_en, new_key, wd_key, new_cmd, wd_cnt));
239 254

  
255
	if (t->wd_hits)
256
		qemu_irq_lower(t->nmi[0]);
257

  
258
	t->wd_hits = 0;
259

  
240 260
	ptimer_set_freq(t->ptimer_wd, 760);
241 261
	if (wd_cnt == 0)
242 262
		wd_cnt = 256;
......
320 340
	qemu_irq_lower(t->irq[0]);
321 341
}
322 342

  
323
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, 
343
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi,
324 344
			target_phys_addr_t base)
325 345
{
326 346
	static struct fs_timer_t *t;
......
337 357
	t->ptimer_t1 = ptimer_init(t->bh_t1);
338 358
	t->ptimer_wd = ptimer_init(t->bh_wd);
339 359
	t->irq = irqs;
360
	t->nmi = nmi;
340 361
	t->env = env;
341 362
	t->base = base;
342 363

  

Also available in: Unified diff