Revision 802670e6 hw/ppc4xx_devs.c

b/hw/ppc4xx_devs.c
66 66
}
67 67

  
68 68
/*****************************************************************************/
69
/* Fake device used to map multiple devices in a single memory page */
70
#define MMIO_AREA_BITS 8
71
#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
72
#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
73
#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
74
struct ppc4xx_mmio_t {
75
    target_phys_addr_t base;
76
    CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
77
    CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
78
    void *opaque[MMIO_AREA_NB];
79
};
80

  
81
static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
82
{
83
#ifdef DEBUG_UNASSIGNED
84
    ppc4xx_mmio_t *mmio;
85

  
86
    mmio = opaque;
87
    printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
88
           addr, mmio->base);
89
#endif
90

  
91
    return 0;
92
}
93

  
94
static void unassigned_mmio_writeb (void *opaque,
95
                                    target_phys_addr_t addr, uint32_t val)
96
{
97
#ifdef DEBUG_UNASSIGNED
98
    ppc4xx_mmio_t *mmio;
99

  
100
    mmio = opaque;
101
    printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
102
           addr, val, mmio->base);
103
#endif
104
}
105

  
106
static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
107
    unassigned_mmio_readb,
108
    unassigned_mmio_readb,
109
    unassigned_mmio_readb,
110
};
111

  
112
static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
113
    unassigned_mmio_writeb,
114
    unassigned_mmio_writeb,
115
    unassigned_mmio_writeb,
116
};
117

  
118
static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
119
                              target_phys_addr_t addr, int len)
120
{
121
    CPUReadMemoryFunc **mem_read;
122
    uint32_t ret;
123
    int idx;
124

  
125
    idx = MMIO_IDX(addr);
126
#if defined(DEBUG_MMIO)
127
    printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
128
           mmio, len, addr, idx);
129
#endif
130
    mem_read = mmio->mem_read[idx];
131
    ret = (*mem_read[len])(mmio->opaque[idx], addr);
132

  
133
    return ret;
134
}
135

  
136
static void mmio_writelen (ppc4xx_mmio_t *mmio,
137
                           target_phys_addr_t addr, uint32_t value, int len)
138
{
139
    CPUWriteMemoryFunc **mem_write;
140
    int idx;
141

  
142
    idx = MMIO_IDX(addr);
143
#if defined(DEBUG_MMIO)
144
    printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08" PRIx32 "\n",
145
           __func__, mmio, len, addr, idx, value);
146
#endif
147
    mem_write = mmio->mem_write[idx];
148
    (*mem_write[len])(mmio->opaque[idx], addr, value);
149
}
150

  
151
static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
152
{
153
#if defined(DEBUG_MMIO)
154
    printf("%s: addr " PADDRX "\n", __func__, addr);
155
#endif
156

  
157
    return mmio_readlen(opaque, addr, 0);
158
}
159

  
160
static void mmio_writeb (void *opaque,
161
                         target_phys_addr_t addr, uint32_t value)
162
{
163
#if defined(DEBUG_MMIO)
164
    printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
165
#endif
166
    mmio_writelen(opaque, addr, value, 0);
167
}
168

  
169
static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
170
{
171
#if defined(DEBUG_MMIO)
172
    printf("%s: addr " PADDRX "\n", __func__, addr);
173
#endif
174

  
175
    return mmio_readlen(opaque, addr, 1);
176
}
177

  
178
static void mmio_writew (void *opaque,
179
                         target_phys_addr_t addr, uint32_t value)
180
{
181
#if defined(DEBUG_MMIO)
182
    printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
183
#endif
184
    mmio_writelen(opaque, addr, value, 1);
185
}
186

  
187
static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
188
{
189
#if defined(DEBUG_MMIO)
190
    printf("%s: addr " PADDRX "\n", __func__, addr);
191
#endif
192

  
193
    return mmio_readlen(opaque, addr, 2);
194
}
195

  
196
static void mmio_writel (void *opaque,
197
                         target_phys_addr_t addr, uint32_t value)
198
{
199
#if defined(DEBUG_MMIO)
200
    printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
201
#endif
202
    mmio_writelen(opaque, addr, value, 2);
203
}
204

  
205
static CPUReadMemoryFunc *mmio_read[] = {
206
    &mmio_readb,
207
    &mmio_readw,
208
    &mmio_readl,
209
};
210

  
211
static CPUWriteMemoryFunc *mmio_write[] = {
212
    &mmio_writeb,
213
    &mmio_writew,
214
    &mmio_writel,
215
};
216

  
217
int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
218
                          target_phys_addr_t offset, uint32_t len,
219
                          CPUReadMemoryFunc **mem_read,
220
                          CPUWriteMemoryFunc **mem_write, void *opaque)
221
{
222
    target_phys_addr_t end;
223
    int idx, eidx;
224

  
225
    if ((offset + len) > TARGET_PAGE_SIZE)
226
        return -1;
227
    idx = MMIO_IDX(offset);
228
    end = offset + len - 1;
229
    eidx = MMIO_IDX(end);
230
#if defined(DEBUG_MMIO)
231
    printf("%s: offset " PADDRX " len %08" PRIx32 " " PADDRX " %d %d\n",
232
           __func__, offset, len, end, idx, eidx);
233
#endif
234
    for (; idx <= eidx; idx++) {
235
        mmio->mem_read[idx] = mem_read;
236
        mmio->mem_write[idx] = mem_write;
237
        mmio->opaque[idx] = opaque;
238
    }
239

  
240
    return 0;
241
}
242

  
243
ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
244
{
245
    ppc4xx_mmio_t *mmio;
246
    int mmio_memory;
247

  
248
    mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
249
    mmio->base = base;
250
    mmio_memory = cpu_register_io_memory(mmio_read, mmio_write, mmio);
251
#if defined(DEBUG_MMIO)
252
    printf("%s: base " PADDRX " len %08x %d\n", __func__,
253
           base, TARGET_PAGE_SIZE, mmio_memory);
254
#endif
255
    cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
256
    ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
257
                         unassigned_mmio_read, unassigned_mmio_write,
258
                         mmio);
259

  
260
    return mmio;
261
}
262

  
263
/*****************************************************************************/
264 69
/* "Universal" Interrupt controller */
265 70
enum {
266 71
    DCR_UICSR  = 0x000,

Also available in: Unified diff