Revision 1ae41f44

b/hw/Makefile.objs
39 39
# PPC devices
40 40
hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
41 41
hw-obj-$(CONFIG_I82378) += i82378.o
42
hw-obj-$(CONFIG_PC87312) += pc87312.o
42 43
# Mac shared devices
43 44
hw-obj-$(CONFIG_MACIO) += macio.o
44 45
hw-obj-$(CONFIG_CUDA) += cuda.o
b/hw/pc87312.c
1
/*
2
 * QEMU National Semiconductor PC87312 (Super I/O)
3
 *
4
 * Copyright (c) 2010-2012 Herve Poussineau
5
 * Copyright (c) 2011-2012 Andreas Färber
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25

  
26
#include "pc87312.h"
27
#include "blockdev.h"
28
#include "sysemu.h"
29
#include "trace.h"
30

  
31

  
32
#define REG_FER 0
33
#define REG_FAR 1
34
#define REG_PTR 2
35

  
36
#define FER regs[REG_FER]
37
#define FAR regs[REG_FAR]
38
#define PTR regs[REG_PTR]
39

  
40
#define FER_PARALLEL_EN   0x01
41
#define FER_UART1_EN      0x02
42
#define FER_UART2_EN      0x04
43
#define FER_FDC_EN        0x08
44
#define FER_FDC_4         0x10
45
#define FER_FDC_ADDR      0x20
46
#define FER_IDE_EN        0x40
47
#define FER_IDE_ADDR      0x80
48

  
49
#define FAR_PARALLEL_ADDR 0x03
50
#define FAR_UART1_ADDR    0x0C
51
#define FAR_UART2_ADDR    0x30
52
#define FAR_UART_3_4      0xC0
53

  
54
#define PTR_POWER_DOWN    0x01
55
#define PTR_CLOCK_DOWN    0x02
56
#define PTR_PWDN          0x04
57
#define PTR_IRQ_5_7       0x08
58
#define PTR_UART1_TEST    0x10
59
#define PTR_UART2_TEST    0x20
60
#define PTR_LOCK_CONF     0x40
61
#define PTR_EPP_MODE      0x80
62

  
63

  
64
/* Parallel port */
65

  
66
static inline bool is_parallel_enabled(PC87312State *s)
67
{
68
    return s->FER & FER_PARALLEL_EN;
69
}
70

  
71
static const uint32_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 };
72

  
73
static inline uint32_t get_parallel_iobase(PC87312State *s)
74
{
75
    return parallel_base[s->FAR & FAR_PARALLEL_ADDR];
76
}
77

  
78
static const uint32_t parallel_irq[] = { 5, 7, 5, 0 };
79

  
80
static inline uint32_t get_parallel_irq(PC87312State *s)
81
{
82
    int idx;
83
    idx = (s->FAR & FAR_PARALLEL_ADDR);
84
    if (idx == 0) {
85
        return (s->PTR & PTR_IRQ_5_7) ? 7 : 5;
86
    } else {
87
        return parallel_irq[idx];
88
    }
89
}
90

  
91
static inline bool is_parallel_epp(PC87312State *s)
92
{
93
    return s->PTR & PTR_EPP_MODE;
94
}
95

  
96

  
97
/* UARTs */
98

  
99
static const uint32_t uart_base[2][4] = {
100
    { 0x3e8, 0x338, 0x2e8, 0x220 },
101
    { 0x2e8, 0x238, 0x2e0, 0x228 }
102
};
103

  
104
static inline uint32_t get_uart_iobase(PC87312State *s, int i)
105
{
106
    int idx;
107
    idx = (s->FAR >> (2 * i + 2)) & 0x3;
108
    if (idx == 0) {
109
        return 0x3f8;
110
    } else if (idx == 1) {
111
        return 0x2f8;
112
    } else {
113
        return uart_base[idx & 1][(s->FAR & FAR_UART_3_4) >> 6];
114
    }
115
}
116

  
117
static inline uint32_t get_uart_irq(PC87312State *s, int i)
118
{
119
    int idx;
120
    idx = (s->FAR >> (2 * i + 2)) & 0x3;
121
    return (idx & 1) ? 3 : 4;
122
}
123

  
124
static inline bool is_uart_enabled(PC87312State *s, int i)
125
{
126
    return s->FER & (FER_UART1_EN << i);
127
}
128

  
129

  
130
/* Floppy controller */
131

  
132
static inline bool is_fdc_enabled(PC87312State *s)
133
{
134
    return s->FER & FER_FDC_EN;
135
}
136

  
137
static inline uint32_t get_fdc_iobase(PC87312State *s)
138
{
139
    return (s->FER & FER_FDC_ADDR) ? 0x370 : 0x3f0;
140
}
141

  
142

  
143
/* IDE controller */
144

  
145
static inline bool is_ide_enabled(PC87312State *s)
146
{
147
    return s->FER & FER_IDE_EN;
148
}
149

  
150
static inline uint32_t get_ide_iobase(PC87312State *s)
151
{
152
    return (s->FER & FER_IDE_ADDR) ? 0x170 : 0x1f0;
153
}
154

  
155

  
156
static void reconfigure_devices(PC87312State *s)
157
{
158
    error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)",
159
                 s->FER, s->FAR, s->PTR);
160
}
161

  
162
static void pc87312_soft_reset(PC87312State *s)
163
{
164
    static const uint8_t fer_init[] = {
165
        0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4b, 0x4b,
166
        0x4b, 0x4b, 0x4b, 0x4b, 0x0f, 0x0f, 0x0f, 0x0f,
167
        0x49, 0x49, 0x49, 0x49, 0x07, 0x07, 0x07, 0x07,
168
        0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x08, 0x00,
169
    };
170
    static const uint8_t far_init[] = {
171
        0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x00, 0x01,
172
        0x01, 0x09, 0x08, 0x08, 0x10, 0x11, 0x39, 0x24,
173
        0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x39, 0x24,
174
        0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x10, 0x10,
175
    };
176
    static const uint8_t ptr_init[] = {
177
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
181
    };
182

  
183
    s->read_id_step = 0;
184
    s->selected_index = REG_FER;
185

  
186
    s->FER = fer_init[s->config & 0x1f];
187
    s->FAR = far_init[s->config & 0x1f];
188
    s->PTR = ptr_init[s->config & 0x1f];
189
}
190

  
191
static void pc87312_hard_reset(PC87312State *s)
192
{
193
    pc87312_soft_reset(s);
194
}
195

  
196
static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val)
197
{
198
    PC87312State *s = opaque;
199

  
200
    trace_pc87312_io_write(addr, val);
201

  
202
    if ((addr & 1) == 0) {
203
        /* Index register */
204
        s->read_id_step = 2;
205
        s->selected_index = val;
206
    } else {
207
        /* Data register */
208
        if (s->selected_index < 3) {
209
            s->regs[s->selected_index] = val;
210
            reconfigure_devices(s);
211
        }
212
    }
213
}
214

  
215
static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr)
216
{
217
    PC87312State *s = opaque;
218
    uint32_t val;
219

  
220
    if ((addr & 1) == 0) {
221
        /* Index register */
222
        if (s->read_id_step++ == 0) {
223
            val = 0x88;
224
        } else if (s->read_id_step++ == 1) {
225
            val = 0;
226
        } else {
227
            val = s->selected_index;
228
        }
229
    } else {
230
        /* Data register */
231
        if (s->selected_index < 3) {
232
            val = s->regs[s->selected_index];
233
        } else {
234
            /* Invalid selected index */
235
            val = 0;
236
        }
237
    }
238

  
239
    trace_pc87312_io_read(addr, val);
240
    return val;
241
}
242

  
243
static int pc87312_post_load(void *opaque, int version_id)
244
{
245
    PC87312State *s = opaque;
246

  
247
    reconfigure_devices(s);
248
    return 0;
249
}
250

  
251
static void pc87312_reset(DeviceState *d)
252
{
253
    PC87312State *s = PC87312(d);
254

  
255
    pc87312_soft_reset(s);
256
}
257

  
258
static int pc87312_init(ISADevice *dev)
259
{
260
    PC87312State *s;
261
    DeviceState *d;
262
    ISADevice *isa;
263
    ISABus *bus;
264
    CharDriverState *chr;
265
    DriveInfo *drive;
266
    char name[5];
267
    int i;
268

  
269
    s = PC87312(dev);
270
    bus = isa_bus_from_device(dev);
271
    pc87312_hard_reset(s);
272

  
273
    if (is_parallel_enabled(s)) {
274
        chr = parallel_hds[0];
275
        if (chr == NULL) {
276
            chr = qemu_chr_new("par0", "null", NULL);
277
        }
278
        isa = isa_create(bus, "isa-parallel");
279
        d = DEVICE(isa);
280
        qdev_prop_set_uint32(d, "index", 0);
281
        qdev_prop_set_uint32(d, "iobase", get_parallel_iobase(s));
282
        qdev_prop_set_uint32(d, "irq", get_parallel_irq(s));
283
        qdev_prop_set_chr(d, "chardev", chr);
284
        qdev_init_nofail(d);
285
        s->parallel.dev = isa;
286
        trace_pc87312_info_parallel(get_parallel_iobase(s),
287
                                    get_parallel_irq(s));
288
    }
289

  
290
    for (i = 0; i < 2; i++) {
291
        if (is_uart_enabled(s, i)) {
292
            chr = serial_hds[i];
293
            if (chr == NULL) {
294
                snprintf(name, sizeof(name), "ser%d", i);
295
                chr = qemu_chr_new(name, "null", NULL);
296
            }
297
            isa = isa_create(bus, "isa-serial");
298
            d = DEVICE(isa);
299
            qdev_prop_set_uint32(d, "index", i);
300
            qdev_prop_set_uint32(d, "iobase", get_uart_iobase(s, i));
301
            qdev_prop_set_uint32(d, "irq", get_uart_irq(s, i));
302
            qdev_prop_set_chr(d, "chardev", chr);
303
            qdev_init_nofail(d);
304
            s->uart[i].dev = isa;
305
            trace_pc87312_info_serial(i, get_uart_iobase(s, i),
306
                                      get_uart_irq(s, i));
307
        }
308
    }
309

  
310
    if (is_fdc_enabled(s)) {
311
        isa = isa_create(bus, "isa-fdc");
312
        d = DEVICE(isa);
313
        qdev_prop_set_uint32(d, "iobase", get_fdc_iobase(s));
314
        qdev_prop_set_uint32(d, "irq", 6);
315
        drive = drive_get(IF_FLOPPY, 0, 0);
316
        if (drive != NULL) {
317
            qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv);
318
        }
319
        drive = drive_get(IF_FLOPPY, 0, 1);
320
        if (drive != NULL) {
321
            qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv);
322
        }
323
        qdev_init_nofail(d);
324
        s->fdc.dev = isa;
325
        trace_pc87312_info_floppy(get_fdc_iobase(s));
326
    }
327

  
328
    if (is_ide_enabled(s)) {
329
        isa = isa_create(bus, "isa-ide");
330
        d = DEVICE(isa);
331
        qdev_prop_set_uint32(d, "iobase", get_ide_iobase(s));
332
        qdev_prop_set_uint32(d, "iobase2", get_ide_iobase(s) + 0x206);
333
        qdev_prop_set_uint32(d, "irq", 14);
334
        qdev_init_nofail(d);
335
        s->ide.dev = isa;
336
        trace_pc87312_info_ide(get_ide_iobase(s));
337
    }
338

  
339
    register_ioport_write(s->iobase, 2, 1, pc87312_ioport_write, s);
340
    register_ioport_read(s->iobase, 2, 1, pc87312_ioport_read, s);
341
    return 0;
342
}
343

  
344
static const VMStateDescription vmstate_pc87312 = {
345
    .name = "pc87312",
346
    .version_id = 1,
347
    .minimum_version_id = 1,
348
    .post_load = pc87312_post_load,
349
    .fields = (VMStateField[]) {
350
        VMSTATE_UINT8(read_id_step, PC87312State),
351
        VMSTATE_UINT8(selected_index, PC87312State),
352
        VMSTATE_UINT8_ARRAY(regs, PC87312State, 3),
353
        VMSTATE_END_OF_LIST()
354
    }
355
};
356

  
357
static Property pc87312_properties[] = {
358
    DEFINE_PROP_HEX32("iobase", PC87312State, iobase, 0x398),
359
    DEFINE_PROP_UINT8("config", PC87312State, config, 1),
360
    DEFINE_PROP_END_OF_LIST()
361
};
362

  
363
static void pc87312_class_init(ObjectClass *klass, void *data)
364
{
365
    DeviceClass *dc = DEVICE_CLASS(klass);
366
    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
367

  
368
    ic->init = pc87312_init;
369
    dc->reset = pc87312_reset;
370
    dc->vmsd = &vmstate_pc87312;
371
    dc->props = pc87312_properties;
372
}
373

  
374
static const TypeInfo pc87312_type_info = {
375
    .name          = TYPE_PC87312,
376
    .parent        = TYPE_ISA_DEVICE,
377
    .instance_size = sizeof(PC87312State),
378
    .class_init    = pc87312_class_init,
379
};
380

  
381
static void pc87312_register_types(void)
382
{
383
    type_register_static(&pc87312_type_info);
384
}
385

  
386
type_init(pc87312_register_types)
b/hw/pc87312.h
1
/*
2
 * QEMU National Semiconductor PC87312 (Super I/O)
3
 *
4
 * Copyright (c) 2010-2012 Herve Poussineau
5
 * Copyright (c) 2011-2012 Andreas Färber
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
#ifndef QEMU_PC87312_H
26
#define QEMU_PC87312_H
27

  
28
#include "isa.h"
29

  
30

  
31
#define TYPE_PC87312 "pc87312"
32
#define PC87312(obj) OBJECT_CHECK(PC87312State, (obj), TYPE_PC87312)
33

  
34
typedef struct PC87312State {
35
    ISADevice dev;
36

  
37
    uint32_t iobase;
38
    uint8_t config; /* initial configuration */
39

  
40
    struct {
41
        ISADevice *dev;
42
    } parallel;
43

  
44
    struct {
45
        ISADevice *dev;
46
    } uart[2];
47

  
48
    struct {
49
        ISADevice *dev;
50
        BlockDriverState *drive[2];
51
        uint32_t base;
52
    } fdc;
53

  
54
    struct {
55
        ISADevice *dev;
56
        uint32_t base;
57
    } ide;
58

  
59
    uint8_t read_id_step;
60
    uint8_t selected_index;
61

  
62
    uint8_t regs[3];
63
} PC87312State;
64

  
65

  
66
#endif
b/trace-events
694 694
mipsnet_write(uint64_t addr, uint64_t val) "write addr=0x%" PRIx64 " val=0x%" PRIx64 ""
695 695
mipsnet_irq(uint32_t isr, uint32_t intctl) "set irq to %d (%02x)"
696 696

  
697
# hw/pc87312.c
698
pc87312_io_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
699
pc87312_io_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
700
pc87312_info_floppy(uint32_t base) "base 0x%x"
701
pc87312_info_ide(uint32_t base) "base 0x%x"
702
pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u"
703
pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u"
704

  
697 705
# xen-all.c
698 706
xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx"
699 707
xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "%#"PRIx64" size %#lx, log_dirty %i"

Also available in: Unified diff