~ubuntu-branches/ubuntu/wily/qemu-kvm-spice/wily

« back to all changes in this revision

Viewing changes to hw/slavio_misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-10-19 10:44:56 UTC
  • Revision ID: james.westby@ubuntu.com-20111019104456-xgvskumk3sxi97f4
Tags: upstream-0.15.0+noroms
ImportĀ upstreamĀ versionĀ 0.15.0+noroms

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * QEMU Sparc SLAVIO aux io port emulation
 
3
 *
 
4
 * Copyright (c) 2005 Fabrice Bellard
 
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 "sysemu.h"
 
26
#include "sysbus.h"
 
27
#include "trace.h"
 
28
 
 
29
/*
 
30
 * This is the auxio port, chip control and system control part of
 
31
 * chip STP2001 (Slave I/O), also produced as NCR89C105. See
 
32
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
 
33
 *
 
34
 * This also includes the PMC CPU idle controller.
 
35
 */
 
36
 
 
37
typedef struct MiscState {
 
38
    SysBusDevice busdev;
 
39
    qemu_irq irq;
 
40
    uint32_t dummy;
 
41
    uint8_t config;
 
42
    uint8_t aux1, aux2;
 
43
    uint8_t diag, mctrl;
 
44
    uint8_t sysctrl;
 
45
    uint16_t leds;
 
46
    qemu_irq fdc_tc;
 
47
} MiscState;
 
48
 
 
49
typedef struct APCState {
 
50
    SysBusDevice busdev;
 
51
    qemu_irq cpu_halt;
 
52
} APCState;
 
53
 
 
54
#define MISC_SIZE 1
 
55
#define SYSCTRL_SIZE 4
 
56
 
 
57
#define AUX1_TC        0x02
 
58
 
 
59
#define AUX2_PWROFF    0x01
 
60
#define AUX2_PWRINTCLR 0x02
 
61
#define AUX2_PWRFAIL   0x20
 
62
 
 
63
#define CFG_PWRINTEN   0x08
 
64
 
 
65
#define SYS_RESET      0x01
 
66
#define SYS_RESETSTAT  0x02
 
67
 
 
68
static void slavio_misc_update_irq(void *opaque)
 
69
{
 
70
    MiscState *s = opaque;
 
71
 
 
72
    if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
 
73
        trace_slavio_misc_update_irq_raise();
 
74
        qemu_irq_raise(s->irq);
 
75
    } else {
 
76
        trace_slavio_misc_update_irq_lower();
 
77
        qemu_irq_lower(s->irq);
 
78
    }
 
79
}
 
80
 
 
81
static void slavio_misc_reset(DeviceState *d)
 
82
{
 
83
    MiscState *s = container_of(d, MiscState, busdev.qdev);
 
84
 
 
85
    // Diagnostic and system control registers not cleared in reset
 
86
    s->config = s->aux1 = s->aux2 = s->mctrl = 0;
 
87
}
 
88
 
 
89
static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
 
90
{
 
91
    MiscState *s = opaque;
 
92
 
 
93
    trace_slavio_set_power_fail(power_failing, s->config);
 
94
    if (power_failing && (s->config & CFG_PWRINTEN)) {
 
95
        s->aux2 |= AUX2_PWRFAIL;
 
96
    } else {
 
97
        s->aux2 &= ~AUX2_PWRFAIL;
 
98
    }
 
99
    slavio_misc_update_irq(s);
 
100
}
 
101
 
 
102
static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
 
103
                                  uint32_t val)
 
104
{
 
105
    MiscState *s = opaque;
 
106
 
 
107
    trace_slavio_cfg_mem_writeb(val & 0xff);
 
108
    s->config = val & 0xff;
 
109
    slavio_misc_update_irq(s);
 
110
}
 
111
 
 
112
static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
 
113
{
 
114
    MiscState *s = opaque;
 
115
    uint32_t ret = 0;
 
116
 
 
117
    ret = s->config;
 
118
    trace_slavio_cfg_mem_readb(ret);
 
119
    return ret;
 
120
}
 
121
 
 
122
static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = {
 
123
    slavio_cfg_mem_readb,
 
124
    NULL,
 
125
    NULL,
 
126
};
 
127
 
 
128
static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = {
 
129
    slavio_cfg_mem_writeb,
 
130
    NULL,
 
131
    NULL,
 
132
};
 
133
 
 
134
static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
 
135
                                   uint32_t val)
 
136
{
 
137
    MiscState *s = opaque;
 
138
 
 
139
    trace_slavio_diag_mem_writeb(val & 0xff);
 
140
    s->diag = val & 0xff;
 
141
}
 
142
 
 
143
static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
 
144
{
 
145
    MiscState *s = opaque;
 
146
    uint32_t ret = 0;
 
147
 
 
148
    ret = s->diag;
 
149
    trace_slavio_diag_mem_readb(ret);
 
150
    return ret;
 
151
}
 
152
 
 
153
static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = {
 
154
    slavio_diag_mem_readb,
 
155
    NULL,
 
156
    NULL,
 
157
};
 
158
 
 
159
static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = {
 
160
    slavio_diag_mem_writeb,
 
161
    NULL,
 
162
    NULL,
 
163
};
 
164
 
 
165
static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
 
166
                                  uint32_t val)
 
167
{
 
168
    MiscState *s = opaque;
 
169
 
 
170
    trace_slavio_mdm_mem_writeb(val & 0xff);
 
171
    s->mctrl = val & 0xff;
 
172
}
 
173
 
 
174
static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
 
175
{
 
176
    MiscState *s = opaque;
 
177
    uint32_t ret = 0;
 
178
 
 
179
    ret = s->mctrl;
 
180
    trace_slavio_mdm_mem_readb(ret);
 
181
    return ret;
 
182
}
 
183
 
 
184
static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = {
 
185
    slavio_mdm_mem_readb,
 
186
    NULL,
 
187
    NULL,
 
188
};
 
189
 
 
190
static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = {
 
191
    slavio_mdm_mem_writeb,
 
192
    NULL,
 
193
    NULL,
 
194
};
 
195
 
 
196
static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
 
197
                                   uint32_t val)
 
198
{
 
199
    MiscState *s = opaque;
 
200
 
 
201
    trace_slavio_aux1_mem_writeb(val & 0xff);
 
202
    if (val & AUX1_TC) {
 
203
        // Send a pulse to floppy terminal count line
 
204
        if (s->fdc_tc) {
 
205
            qemu_irq_raise(s->fdc_tc);
 
206
            qemu_irq_lower(s->fdc_tc);
 
207
        }
 
208
        val &= ~AUX1_TC;
 
209
    }
 
210
    s->aux1 = val & 0xff;
 
211
}
 
212
 
 
213
static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
 
214
{
 
215
    MiscState *s = opaque;
 
216
    uint32_t ret = 0;
 
217
 
 
218
    ret = s->aux1;
 
219
    trace_slavio_aux1_mem_readb(ret);
 
220
    return ret;
 
221
}
 
222
 
 
223
static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = {
 
224
    slavio_aux1_mem_readb,
 
225
    NULL,
 
226
    NULL,
 
227
};
 
228
 
 
229
static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = {
 
230
    slavio_aux1_mem_writeb,
 
231
    NULL,
 
232
    NULL,
 
233
};
 
234
 
 
235
static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
 
236
                                   uint32_t val)
 
237
{
 
238
    MiscState *s = opaque;
 
239
 
 
240
    val &= AUX2_PWRINTCLR | AUX2_PWROFF;
 
241
    trace_slavio_aux2_mem_writeb(val & 0xff);
 
242
    val |= s->aux2 & AUX2_PWRFAIL;
 
243
    if (val & AUX2_PWRINTCLR) // Clear Power Fail int
 
244
        val &= AUX2_PWROFF;
 
245
    s->aux2 = val;
 
246
    if (val & AUX2_PWROFF)
 
247
        qemu_system_shutdown_request();
 
248
    slavio_misc_update_irq(s);
 
249
}
 
250
 
 
251
static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
 
252
{
 
253
    MiscState *s = opaque;
 
254
    uint32_t ret = 0;
 
255
 
 
256
    ret = s->aux2;
 
257
    trace_slavio_aux2_mem_readb(ret);
 
258
    return ret;
 
259
}
 
260
 
 
261
static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = {
 
262
    slavio_aux2_mem_readb,
 
263
    NULL,
 
264
    NULL,
 
265
};
 
266
 
 
267
static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
 
268
    slavio_aux2_mem_writeb,
 
269
    NULL,
 
270
    NULL,
 
271
};
 
272
 
 
273
static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 
274
{
 
275
    APCState *s = opaque;
 
276
 
 
277
    trace_apc_mem_writeb(val & 0xff);
 
278
    qemu_irq_raise(s->cpu_halt);
 
279
}
 
280
 
 
281
static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
 
282
{
 
283
    uint32_t ret = 0;
 
284
 
 
285
    trace_apc_mem_readb(ret);
 
286
    return ret;
 
287
}
 
288
 
 
289
static CPUReadMemoryFunc * const apc_mem_read[3] = {
 
290
    apc_mem_readb,
 
291
    NULL,
 
292
    NULL,
 
293
};
 
294
 
 
295
static CPUWriteMemoryFunc * const apc_mem_write[3] = {
 
296
    apc_mem_writeb,
 
297
    NULL,
 
298
    NULL,
 
299
};
 
300
 
 
301
static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
 
302
{
 
303
    MiscState *s = opaque;
 
304
    uint32_t ret = 0;
 
305
 
 
306
    switch (addr) {
 
307
    case 0:
 
308
        ret = s->sysctrl;
 
309
        break;
 
310
    default:
 
311
        break;
 
312
    }
 
313
    trace_slavio_sysctrl_mem_readl(ret);
 
314
    return ret;
 
315
}
 
316
 
 
317
static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
 
318
                                      uint32_t val)
 
319
{
 
320
    MiscState *s = opaque;
 
321
 
 
322
    trace_slavio_sysctrl_mem_writel(val);
 
323
    switch (addr) {
 
324
    case 0:
 
325
        if (val & SYS_RESET) {
 
326
            s->sysctrl = SYS_RESETSTAT;
 
327
            qemu_system_reset_request();
 
328
        }
 
329
        break;
 
330
    default:
 
331
        break;
 
332
    }
 
333
}
 
334
 
 
335
static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = {
 
336
    NULL,
 
337
    NULL,
 
338
    slavio_sysctrl_mem_readl,
 
339
};
 
340
 
 
341
static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
 
342
    NULL,
 
343
    NULL,
 
344
    slavio_sysctrl_mem_writel,
 
345
};
 
346
 
 
347
static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
 
348
{
 
349
    MiscState *s = opaque;
 
350
    uint32_t ret = 0;
 
351
 
 
352
    switch (addr) {
 
353
    case 0:
 
354
        ret = s->leds;
 
355
        break;
 
356
    default:
 
357
        break;
 
358
    }
 
359
    trace_slavio_led_mem_readw(ret);
 
360
    return ret;
 
361
}
 
362
 
 
363
static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
 
364
                                  uint32_t val)
 
365
{
 
366
    MiscState *s = opaque;
 
367
 
 
368
    trace_slavio_led_mem_readw(val & 0xffff);
 
369
    switch (addr) {
 
370
    case 0:
 
371
        s->leds = val;
 
372
        break;
 
373
    default:
 
374
        break;
 
375
    }
 
376
}
 
377
 
 
378
static CPUReadMemoryFunc * const slavio_led_mem_read[3] = {
 
379
    NULL,
 
380
    slavio_led_mem_readw,
 
381
    NULL,
 
382
};
 
383
 
 
384
static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = {
 
385
    NULL,
 
386
    slavio_led_mem_writew,
 
387
    NULL,
 
388
};
 
389
 
 
390
static const VMStateDescription vmstate_misc = {
 
391
    .name ="slavio_misc",
 
392
    .version_id = 1,
 
393
    .minimum_version_id = 1,
 
394
    .minimum_version_id_old = 1,
 
395
    .fields      = (VMStateField []) {
 
396
        VMSTATE_UINT32(dummy, MiscState),
 
397
        VMSTATE_UINT8(config, MiscState),
 
398
        VMSTATE_UINT8(aux1, MiscState),
 
399
        VMSTATE_UINT8(aux2, MiscState),
 
400
        VMSTATE_UINT8(diag, MiscState),
 
401
        VMSTATE_UINT8(mctrl, MiscState),
 
402
        VMSTATE_UINT8(sysctrl, MiscState),
 
403
        VMSTATE_END_OF_LIST()
 
404
    }
 
405
};
 
406
 
 
407
static int apc_init1(SysBusDevice *dev)
 
408
{
 
409
    APCState *s = FROM_SYSBUS(APCState, dev);
 
410
    int io;
 
411
 
 
412
    sysbus_init_irq(dev, &s->cpu_halt);
 
413
 
 
414
    /* Power management (APC) XXX: not a Slavio device */
 
415
    io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s,
 
416
                                DEVICE_NATIVE_ENDIAN);
 
417
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
418
    return 0;
 
419
}
 
420
 
 
421
static int slavio_misc_init1(SysBusDevice *dev)
 
422
{
 
423
    MiscState *s = FROM_SYSBUS(MiscState, dev);
 
424
    int io;
 
425
 
 
426
    sysbus_init_irq(dev, &s->irq);
 
427
    sysbus_init_irq(dev, &s->fdc_tc);
 
428
 
 
429
    /* 8 bit registers */
 
430
    /* Slavio control */
 
431
    io = cpu_register_io_memory(slavio_cfg_mem_read,
 
432
                                slavio_cfg_mem_write, s,
 
433
                                DEVICE_NATIVE_ENDIAN);
 
434
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
435
 
 
436
    /* Diagnostics */
 
437
    io = cpu_register_io_memory(slavio_diag_mem_read,
 
438
                                slavio_diag_mem_write, s,
 
439
                                DEVICE_NATIVE_ENDIAN);
 
440
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
441
 
 
442
    /* Modem control */
 
443
    io = cpu_register_io_memory(slavio_mdm_mem_read,
 
444
                                slavio_mdm_mem_write, s,
 
445
                                DEVICE_NATIVE_ENDIAN);
 
446
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
447
 
 
448
    /* 16 bit registers */
 
449
    /* ss600mp diag LEDs */
 
450
    io = cpu_register_io_memory(slavio_led_mem_read,
 
451
                                slavio_led_mem_write, s,
 
452
                                DEVICE_NATIVE_ENDIAN);
 
453
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
454
 
 
455
    /* 32 bit registers */
 
456
    /* System control */
 
457
    io = cpu_register_io_memory(slavio_sysctrl_mem_read,
 
458
                                slavio_sysctrl_mem_write, s,
 
459
                                DEVICE_NATIVE_ENDIAN);
 
460
    sysbus_init_mmio(dev, SYSCTRL_SIZE, io);
 
461
 
 
462
    /* AUX 1 (Misc System Functions) */
 
463
    io = cpu_register_io_memory(slavio_aux1_mem_read,
 
464
                                slavio_aux1_mem_write, s,
 
465
                                DEVICE_NATIVE_ENDIAN);
 
466
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
467
 
 
468
    /* AUX 2 (Software Powerdown Control) */
 
469
    io = cpu_register_io_memory(slavio_aux2_mem_read,
 
470
                                slavio_aux2_mem_write, s,
 
471
                                DEVICE_NATIVE_ENDIAN);
 
472
    sysbus_init_mmio(dev, MISC_SIZE, io);
 
473
 
 
474
    qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
 
475
 
 
476
    return 0;
 
477
}
 
478
 
 
479
static SysBusDeviceInfo slavio_misc_info = {
 
480
    .init = slavio_misc_init1,
 
481
    .qdev.name  = "slavio_misc",
 
482
    .qdev.size  = sizeof(MiscState),
 
483
    .qdev.vmsd  = &vmstate_misc,
 
484
    .qdev.reset  = slavio_misc_reset,
 
485
};
 
486
 
 
487
static SysBusDeviceInfo apc_info = {
 
488
    .init = apc_init1,
 
489
    .qdev.name  = "apc",
 
490
    .qdev.size  = sizeof(MiscState),
 
491
};
 
492
 
 
493
static void slavio_misc_register_devices(void)
 
494
{
 
495
    sysbus_register_withprop(&slavio_misc_info);
 
496
    sysbus_register_withprop(&apc_info);
 
497
}
 
498
 
 
499
device_init(slavio_misc_register_devices)