149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * QEMU National Semiconductor PC87312 (Super I/O)
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2010-2012 Herve Poussineau
549ab747fSPaolo Bonzini * Copyright (c) 2011-2012 Andreas Färber
649ab747fSPaolo Bonzini *
749ab747fSPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
849ab747fSPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
949ab747fSPaolo Bonzini * in the Software without restriction, including without limitation the rights
1049ab747fSPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1149ab747fSPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
1249ab747fSPaolo Bonzini * furnished to do so, subject to the following conditions:
1349ab747fSPaolo Bonzini *
1449ab747fSPaolo Bonzini * The above copyright notice and this permission notice shall be included in
1549ab747fSPaolo Bonzini * all copies or substantial portions of the Software.
1649ab747fSPaolo Bonzini *
1749ab747fSPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1849ab747fSPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1949ab747fSPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2049ab747fSPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2149ab747fSPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2249ab747fSPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2349ab747fSPaolo Bonzini * THE SOFTWARE.
2449ab747fSPaolo Bonzini */
2549ab747fSPaolo Bonzini
260d75590dSPeter Maydell #include "qemu/osdep.h"
2749ab747fSPaolo Bonzini #include "hw/isa/pc87312.h"
28a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
29d6454270SMarkus Armbruster #include "migration/vmstate.h"
30da34e65cSMarkus Armbruster #include "qapi/error.h"
3149ab747fSPaolo Bonzini #include "qemu/error-report.h"
320b8fa32fSMarkus Armbruster #include "qemu/module.h"
3349ab747fSPaolo Bonzini #include "trace.h"
3449ab747fSPaolo Bonzini
3549ab747fSPaolo Bonzini
3649ab747fSPaolo Bonzini #define REG_FER 0
3749ab747fSPaolo Bonzini #define REG_FAR 1
3849ab747fSPaolo Bonzini #define REG_PTR 2
3949ab747fSPaolo Bonzini
4049ab747fSPaolo Bonzini #define FER_PARALLEL_EN 0x01
4149ab747fSPaolo Bonzini #define FER_UART1_EN 0x02
4249ab747fSPaolo Bonzini #define FER_UART2_EN 0x04
4349ab747fSPaolo Bonzini #define FER_FDC_EN 0x08
4449ab747fSPaolo Bonzini #define FER_FDC_4 0x10
4549ab747fSPaolo Bonzini #define FER_FDC_ADDR 0x20
4649ab747fSPaolo Bonzini #define FER_IDE_EN 0x40
4749ab747fSPaolo Bonzini #define FER_IDE_ADDR 0x80
4849ab747fSPaolo Bonzini
4949ab747fSPaolo Bonzini #define FAR_PARALLEL_ADDR 0x03
5049ab747fSPaolo Bonzini #define FAR_UART1_ADDR 0x0C
5149ab747fSPaolo Bonzini #define FAR_UART2_ADDR 0x30
5249ab747fSPaolo Bonzini #define FAR_UART_3_4 0xC0
5349ab747fSPaolo Bonzini
5449ab747fSPaolo Bonzini #define PTR_POWER_DOWN 0x01
5549ab747fSPaolo Bonzini #define PTR_CLOCK_DOWN 0x02
5649ab747fSPaolo Bonzini #define PTR_PWDN 0x04
5749ab747fSPaolo Bonzini #define PTR_IRQ_5_7 0x08
5849ab747fSPaolo Bonzini #define PTR_UART1_TEST 0x10
5949ab747fSPaolo Bonzini #define PTR_UART2_TEST 0x20
6049ab747fSPaolo Bonzini #define PTR_LOCK_CONF 0x40
6149ab747fSPaolo Bonzini #define PTR_EPP_MODE 0x80
6249ab747fSPaolo Bonzini
6349ab747fSPaolo Bonzini
6449ab747fSPaolo Bonzini /* Parallel port */
6549ab747fSPaolo Bonzini
is_parallel_enabled(ISASuperIODevice * sio,uint8_t index)664c3119a6SPhilippe Mathieu-Daudé static bool is_parallel_enabled(ISASuperIODevice *sio, uint8_t index)
6749ab747fSPaolo Bonzini {
684c3119a6SPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
694c3119a6SPhilippe Mathieu-Daudé return index ? false : s->regs[REG_FER] & FER_PARALLEL_EN;
7049ab747fSPaolo Bonzini }
7149ab747fSPaolo Bonzini
724e00105aSPhilippe Mathieu-Daudé static const uint16_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 };
7349ab747fSPaolo Bonzini
get_parallel_iobase(ISASuperIODevice * sio,uint8_t index)744c3119a6SPhilippe Mathieu-Daudé static uint16_t get_parallel_iobase(ISASuperIODevice *sio, uint8_t index)
7549ab747fSPaolo Bonzini {
764c3119a6SPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
7749ab747fSPaolo Bonzini return parallel_base[s->regs[REG_FAR] & FAR_PARALLEL_ADDR];
7849ab747fSPaolo Bonzini }
7949ab747fSPaolo Bonzini
80818c9d99SPhilippe Mathieu-Daudé static const unsigned int parallel_irq[] = { 5, 7, 5, 0 };
8149ab747fSPaolo Bonzini
get_parallel_irq(ISASuperIODevice * sio,uint8_t index)824c3119a6SPhilippe Mathieu-Daudé static unsigned int get_parallel_irq(ISASuperIODevice *sio, uint8_t index)
8349ab747fSPaolo Bonzini {
844c3119a6SPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
8549ab747fSPaolo Bonzini int idx;
8649ab747fSPaolo Bonzini idx = (s->regs[REG_FAR] & FAR_PARALLEL_ADDR);
8749ab747fSPaolo Bonzini if (idx == 0) {
8849ab747fSPaolo Bonzini return (s->regs[REG_PTR] & PTR_IRQ_5_7) ? 7 : 5;
8949ab747fSPaolo Bonzini } else {
9049ab747fSPaolo Bonzini return parallel_irq[idx];
9149ab747fSPaolo Bonzini }
9249ab747fSPaolo Bonzini }
9349ab747fSPaolo Bonzini
9449ab747fSPaolo Bonzini
9549ab747fSPaolo Bonzini /* UARTs */
9649ab747fSPaolo Bonzini
974e00105aSPhilippe Mathieu-Daudé static const uint16_t uart_base[2][4] = {
9849ab747fSPaolo Bonzini { 0x3e8, 0x338, 0x2e8, 0x220 },
9949ab747fSPaolo Bonzini { 0x2e8, 0x238, 0x2e0, 0x228 }
10049ab747fSPaolo Bonzini };
10149ab747fSPaolo Bonzini
get_uart_iobase(ISASuperIODevice * sio,uint8_t i)102cd9526abSPhilippe Mathieu-Daudé static uint16_t get_uart_iobase(ISASuperIODevice *sio, uint8_t i)
10349ab747fSPaolo Bonzini {
104cd9526abSPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
10549ab747fSPaolo Bonzini int idx;
10649ab747fSPaolo Bonzini idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3;
10749ab747fSPaolo Bonzini if (idx == 0) {
10849ab747fSPaolo Bonzini return 0x3f8;
10949ab747fSPaolo Bonzini } else if (idx == 1) {
11049ab747fSPaolo Bonzini return 0x2f8;
11149ab747fSPaolo Bonzini } else {
11249ab747fSPaolo Bonzini return uart_base[idx & 1][(s->regs[REG_FAR] & FAR_UART_3_4) >> 6];
11349ab747fSPaolo Bonzini }
11449ab747fSPaolo Bonzini }
11549ab747fSPaolo Bonzini
get_uart_irq(ISASuperIODevice * sio,uint8_t i)116cd9526abSPhilippe Mathieu-Daudé static unsigned int get_uart_irq(ISASuperIODevice *sio, uint8_t i)
11749ab747fSPaolo Bonzini {
118cd9526abSPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
11949ab747fSPaolo Bonzini int idx;
12049ab747fSPaolo Bonzini idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3;
12149ab747fSPaolo Bonzini return (idx & 1) ? 3 : 4;
12249ab747fSPaolo Bonzini }
12349ab747fSPaolo Bonzini
is_uart_enabled(ISASuperIODevice * sio,uint8_t i)124cd9526abSPhilippe Mathieu-Daudé static bool is_uart_enabled(ISASuperIODevice *sio, uint8_t i)
12549ab747fSPaolo Bonzini {
126cd9526abSPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
12749ab747fSPaolo Bonzini return s->regs[REG_FER] & (FER_UART1_EN << i);
12849ab747fSPaolo Bonzini }
12949ab747fSPaolo Bonzini
13049ab747fSPaolo Bonzini
13149ab747fSPaolo Bonzini /* Floppy controller */
13249ab747fSPaolo Bonzini
is_fdc_enabled(ISASuperIODevice * sio,uint8_t index)1336f6695b1SPhilippe Mathieu-Daudé static bool is_fdc_enabled(ISASuperIODevice *sio, uint8_t index)
13449ab747fSPaolo Bonzini {
1356f6695b1SPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
1366f6695b1SPhilippe Mathieu-Daudé assert(!index);
13749ab747fSPaolo Bonzini return s->regs[REG_FER] & FER_FDC_EN;
13849ab747fSPaolo Bonzini }
13949ab747fSPaolo Bonzini
get_fdc_iobase(ISASuperIODevice * sio,uint8_t index)1406f6695b1SPhilippe Mathieu-Daudé static uint16_t get_fdc_iobase(ISASuperIODevice *sio, uint8_t index)
14149ab747fSPaolo Bonzini {
1426f6695b1SPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
1436f6695b1SPhilippe Mathieu-Daudé assert(!index);
14449ab747fSPaolo Bonzini return (s->regs[REG_FER] & FER_FDC_ADDR) ? 0x370 : 0x3f0;
14549ab747fSPaolo Bonzini }
14649ab747fSPaolo Bonzini
get_fdc_irq(ISASuperIODevice * sio,uint8_t index)1476f6695b1SPhilippe Mathieu-Daudé static unsigned int get_fdc_irq(ISASuperIODevice *sio, uint8_t index)
1486f6695b1SPhilippe Mathieu-Daudé {
1496f6695b1SPhilippe Mathieu-Daudé assert(!index);
1506f6695b1SPhilippe Mathieu-Daudé return 6;
1516f6695b1SPhilippe Mathieu-Daudé }
1526f6695b1SPhilippe Mathieu-Daudé
15349ab747fSPaolo Bonzini
15449ab747fSPaolo Bonzini /* IDE controller */
15549ab747fSPaolo Bonzini
is_ide_enabled(ISASuperIODevice * sio,uint8_t index)156c16a4e1bSPhilippe Mathieu-Daudé static bool is_ide_enabled(ISASuperIODevice *sio, uint8_t index)
15749ab747fSPaolo Bonzini {
158c16a4e1bSPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
159c16a4e1bSPhilippe Mathieu-Daudé
16049ab747fSPaolo Bonzini return s->regs[REG_FER] & FER_IDE_EN;
16149ab747fSPaolo Bonzini }
16249ab747fSPaolo Bonzini
get_ide_iobase(ISASuperIODevice * sio,uint8_t index)163c16a4e1bSPhilippe Mathieu-Daudé static uint16_t get_ide_iobase(ISASuperIODevice *sio, uint8_t index)
16449ab747fSPaolo Bonzini {
165c16a4e1bSPhilippe Mathieu-Daudé PC87312State *s = PC87312(sio);
166c16a4e1bSPhilippe Mathieu-Daudé
167c16a4e1bSPhilippe Mathieu-Daudé if (index == 1) {
168c16a4e1bSPhilippe Mathieu-Daudé return get_ide_iobase(sio, 0) + 0x206;
169c16a4e1bSPhilippe Mathieu-Daudé }
17049ab747fSPaolo Bonzini return (s->regs[REG_FER] & FER_IDE_ADDR) ? 0x170 : 0x1f0;
17149ab747fSPaolo Bonzini }
17249ab747fSPaolo Bonzini
get_ide_irq(ISASuperIODevice * sio,uint8_t index)173c16a4e1bSPhilippe Mathieu-Daudé static unsigned int get_ide_irq(ISASuperIODevice *sio, uint8_t index)
174c16a4e1bSPhilippe Mathieu-Daudé {
175c16a4e1bSPhilippe Mathieu-Daudé assert(index == 0);
176c16a4e1bSPhilippe Mathieu-Daudé return 14;
177c16a4e1bSPhilippe Mathieu-Daudé }
17849ab747fSPaolo Bonzini
reconfigure_devices(PC87312State * s)17949ab747fSPaolo Bonzini static void reconfigure_devices(PC87312State *s)
18049ab747fSPaolo Bonzini {
18149ab747fSPaolo Bonzini error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)",
18249ab747fSPaolo Bonzini s->regs[REG_FER], s->regs[REG_FAR], s->regs[REG_PTR]);
18349ab747fSPaolo Bonzini }
18449ab747fSPaolo Bonzini
pc87312_soft_reset(PC87312State * s)18549ab747fSPaolo Bonzini static void pc87312_soft_reset(PC87312State *s)
18649ab747fSPaolo Bonzini {
18749ab747fSPaolo Bonzini static const uint8_t fer_init[] = {
18849ab747fSPaolo Bonzini 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4b, 0x4b,
18949ab747fSPaolo Bonzini 0x4b, 0x4b, 0x4b, 0x4b, 0x0f, 0x0f, 0x0f, 0x0f,
19049ab747fSPaolo Bonzini 0x49, 0x49, 0x49, 0x49, 0x07, 0x07, 0x07, 0x07,
19149ab747fSPaolo Bonzini 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x08, 0x00,
19249ab747fSPaolo Bonzini };
19349ab747fSPaolo Bonzini static const uint8_t far_init[] = {
19449ab747fSPaolo Bonzini 0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x00, 0x01,
19549ab747fSPaolo Bonzini 0x01, 0x09, 0x08, 0x08, 0x10, 0x11, 0x39, 0x24,
19649ab747fSPaolo Bonzini 0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x39, 0x24,
19749ab747fSPaolo Bonzini 0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x10, 0x10,
19849ab747fSPaolo Bonzini };
19949ab747fSPaolo Bonzini static const uint8_t ptr_init[] = {
20049ab747fSPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20149ab747fSPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20249ab747fSPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20349ab747fSPaolo Bonzini 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
20449ab747fSPaolo Bonzini };
20549ab747fSPaolo Bonzini
20649ab747fSPaolo Bonzini s->read_id_step = 0;
20749ab747fSPaolo Bonzini s->selected_index = REG_FER;
20849ab747fSPaolo Bonzini
20949ab747fSPaolo Bonzini s->regs[REG_FER] = fer_init[s->config & 0x1f];
21049ab747fSPaolo Bonzini s->regs[REG_FAR] = far_init[s->config & 0x1f];
21149ab747fSPaolo Bonzini s->regs[REG_PTR] = ptr_init[s->config & 0x1f];
21249ab747fSPaolo Bonzini }
21349ab747fSPaolo Bonzini
pc87312_hard_reset(PC87312State * s)21449ab747fSPaolo Bonzini static void pc87312_hard_reset(PC87312State *s)
21549ab747fSPaolo Bonzini {
21649ab747fSPaolo Bonzini pc87312_soft_reset(s);
21749ab747fSPaolo Bonzini }
21849ab747fSPaolo Bonzini
pc87312_io_write(void * opaque,hwaddr addr,uint64_t val,unsigned int size)21949ab747fSPaolo Bonzini static void pc87312_io_write(void *opaque, hwaddr addr, uint64_t val,
22049ab747fSPaolo Bonzini unsigned int size)
22149ab747fSPaolo Bonzini {
22249ab747fSPaolo Bonzini PC87312State *s = opaque;
22349ab747fSPaolo Bonzini
22449ab747fSPaolo Bonzini trace_pc87312_io_write(addr, val);
22549ab747fSPaolo Bonzini
22649ab747fSPaolo Bonzini if ((addr & 1) == 0) {
22749ab747fSPaolo Bonzini /* Index register */
22849ab747fSPaolo Bonzini s->read_id_step = 2;
22949ab747fSPaolo Bonzini s->selected_index = val;
23049ab747fSPaolo Bonzini } else {
23149ab747fSPaolo Bonzini /* Data register */
23249ab747fSPaolo Bonzini if (s->selected_index < 3) {
23349ab747fSPaolo Bonzini s->regs[s->selected_index] = val;
23449ab747fSPaolo Bonzini reconfigure_devices(s);
23549ab747fSPaolo Bonzini }
23649ab747fSPaolo Bonzini }
23749ab747fSPaolo Bonzini }
23849ab747fSPaolo Bonzini
pc87312_io_read(void * opaque,hwaddr addr,unsigned int size)23949ab747fSPaolo Bonzini static uint64_t pc87312_io_read(void *opaque, hwaddr addr, unsigned int size)
24049ab747fSPaolo Bonzini {
24149ab747fSPaolo Bonzini PC87312State *s = opaque;
24249ab747fSPaolo Bonzini uint32_t val;
24349ab747fSPaolo Bonzini
24449ab747fSPaolo Bonzini if ((addr & 1) == 0) {
24549ab747fSPaolo Bonzini /* Index register */
24649ab747fSPaolo Bonzini if (s->read_id_step++ == 0) {
24749ab747fSPaolo Bonzini val = 0x88;
24849ab747fSPaolo Bonzini } else if (s->read_id_step++ == 1) {
24949ab747fSPaolo Bonzini val = 0;
25049ab747fSPaolo Bonzini } else {
25149ab747fSPaolo Bonzini val = s->selected_index;
25249ab747fSPaolo Bonzini }
25349ab747fSPaolo Bonzini } else {
25449ab747fSPaolo Bonzini /* Data register */
25549ab747fSPaolo Bonzini if (s->selected_index < 3) {
25649ab747fSPaolo Bonzini val = s->regs[s->selected_index];
25749ab747fSPaolo Bonzini } else {
25849ab747fSPaolo Bonzini /* Invalid selected index */
25949ab747fSPaolo Bonzini val = 0;
26049ab747fSPaolo Bonzini }
26149ab747fSPaolo Bonzini }
26249ab747fSPaolo Bonzini
26349ab747fSPaolo Bonzini trace_pc87312_io_read(addr, val);
26449ab747fSPaolo Bonzini return val;
26549ab747fSPaolo Bonzini }
26649ab747fSPaolo Bonzini
26749ab747fSPaolo Bonzini static const MemoryRegionOps pc87312_io_ops = {
26849ab747fSPaolo Bonzini .read = pc87312_io_read,
26949ab747fSPaolo Bonzini .write = pc87312_io_write,
27049ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
27149ab747fSPaolo Bonzini .valid = {
27249ab747fSPaolo Bonzini .min_access_size = 1,
27349ab747fSPaolo Bonzini .max_access_size = 1,
27449ab747fSPaolo Bonzini },
27549ab747fSPaolo Bonzini };
27649ab747fSPaolo Bonzini
pc87312_post_load(void * opaque,int version_id)27749ab747fSPaolo Bonzini static int pc87312_post_load(void *opaque, int version_id)
27849ab747fSPaolo Bonzini {
27949ab747fSPaolo Bonzini PC87312State *s = opaque;
28049ab747fSPaolo Bonzini
28149ab747fSPaolo Bonzini reconfigure_devices(s);
28249ab747fSPaolo Bonzini return 0;
28349ab747fSPaolo Bonzini }
28449ab747fSPaolo Bonzini
pc87312_reset(DeviceState * d)28549ab747fSPaolo Bonzini static void pc87312_reset(DeviceState *d)
28649ab747fSPaolo Bonzini {
28749ab747fSPaolo Bonzini PC87312State *s = PC87312(d);
28849ab747fSPaolo Bonzini
28949ab747fSPaolo Bonzini pc87312_soft_reset(s);
29049ab747fSPaolo Bonzini }
29149ab747fSPaolo Bonzini
pc87312_realize(DeviceState * dev,Error ** errp)292db895a1eSAndreas Färber static void pc87312_realize(DeviceState *dev, Error **errp)
29349ab747fSPaolo Bonzini {
29449ab747fSPaolo Bonzini PC87312State *s;
29549ab747fSPaolo Bonzini ISADevice *isa;
29663f01a74SPhilippe Mathieu-Daudé Error *local_err = NULL;
29749ab747fSPaolo Bonzini
29849ab747fSPaolo Bonzini s = PC87312(dev);
299db895a1eSAndreas Färber isa = ISA_DEVICE(dev);
300db895a1eSAndreas Färber isa_register_ioport(isa, &s->io, s->iobase);
30149ab747fSPaolo Bonzini pc87312_hard_reset(s);
30249ab747fSPaolo Bonzini
30363f01a74SPhilippe Mathieu-Daudé ISA_SUPERIO_GET_CLASS(dev)->parent_realize(dev, &local_err);
30463f01a74SPhilippe Mathieu-Daudé if (local_err) {
30563f01a74SPhilippe Mathieu-Daudé error_propagate(errp, local_err);
30663f01a74SPhilippe Mathieu-Daudé return;
30763f01a74SPhilippe Mathieu-Daudé }
30849ab747fSPaolo Bonzini }
30949ab747fSPaolo Bonzini
pc87312_initfn(Object * obj)31049ab747fSPaolo Bonzini static void pc87312_initfn(Object *obj)
31149ab747fSPaolo Bonzini {
31249ab747fSPaolo Bonzini PC87312State *s = PC87312(obj);
31349ab747fSPaolo Bonzini
3141437c94bSPaolo Bonzini memory_region_init_io(&s->io, obj, &pc87312_io_ops, s, "pc87312", 2);
31549ab747fSPaolo Bonzini }
31649ab747fSPaolo Bonzini
31749ab747fSPaolo Bonzini static const VMStateDescription vmstate_pc87312 = {
31849ab747fSPaolo Bonzini .name = "pc87312",
31949ab747fSPaolo Bonzini .version_id = 1,
32049ab747fSPaolo Bonzini .minimum_version_id = 1,
32149ab747fSPaolo Bonzini .post_load = pc87312_post_load,
322cbf19506SRichard Henderson .fields = (const VMStateField[]) {
32349ab747fSPaolo Bonzini VMSTATE_UINT8(read_id_step, PC87312State),
32449ab747fSPaolo Bonzini VMSTATE_UINT8(selected_index, PC87312State),
32549ab747fSPaolo Bonzini VMSTATE_UINT8_ARRAY(regs, PC87312State, 3),
32649ab747fSPaolo Bonzini VMSTATE_END_OF_LIST()
32749ab747fSPaolo Bonzini }
32849ab747fSPaolo Bonzini };
32949ab747fSPaolo Bonzini
33049ab747fSPaolo Bonzini static Property pc87312_properties[] = {
3314e00105aSPhilippe Mathieu-Daudé DEFINE_PROP_UINT16("iobase", PC87312State, iobase, 0x398),
33249ab747fSPaolo Bonzini DEFINE_PROP_UINT8("config", PC87312State, config, 1),
33349ab747fSPaolo Bonzini DEFINE_PROP_END_OF_LIST()
33449ab747fSPaolo Bonzini };
33549ab747fSPaolo Bonzini
pc87312_class_init(ObjectClass * klass,void * data)33649ab747fSPaolo Bonzini static void pc87312_class_init(ObjectClass *klass, void *data)
33749ab747fSPaolo Bonzini {
33849ab747fSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass);
33963f01a74SPhilippe Mathieu-Daudé ISASuperIOClass *sc = ISA_SUPERIO_CLASS(klass);
34049ab747fSPaolo Bonzini
341*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, pc87312_reset);
34249ab747fSPaolo Bonzini dc->vmsd = &vmstate_pc87312;
343f669bd89SZhao Liu device_class_set_parent_realize(dc, pc87312_realize,
344f669bd89SZhao Liu &sc->parent_realize);
3454f67d30bSMarc-André Lureau device_class_set_props(dc, pc87312_properties);
3464c3119a6SPhilippe Mathieu-Daudé
3474c3119a6SPhilippe Mathieu-Daudé sc->parallel = (ISASuperIOFuncs){
3484c3119a6SPhilippe Mathieu-Daudé .count = 1,
3494c3119a6SPhilippe Mathieu-Daudé .is_enabled = is_parallel_enabled,
3504c3119a6SPhilippe Mathieu-Daudé .get_iobase = get_parallel_iobase,
3514c3119a6SPhilippe Mathieu-Daudé .get_irq = get_parallel_irq,
3524c3119a6SPhilippe Mathieu-Daudé };
353cd9526abSPhilippe Mathieu-Daudé sc->serial = (ISASuperIOFuncs){
354cd9526abSPhilippe Mathieu-Daudé .count = 2,
355cd9526abSPhilippe Mathieu-Daudé .is_enabled = is_uart_enabled,
356cd9526abSPhilippe Mathieu-Daudé .get_iobase = get_uart_iobase,
357cd9526abSPhilippe Mathieu-Daudé .get_irq = get_uart_irq,
358cd9526abSPhilippe Mathieu-Daudé };
3596f6695b1SPhilippe Mathieu-Daudé sc->floppy = (ISASuperIOFuncs){
3606f6695b1SPhilippe Mathieu-Daudé .count = 1,
3616f6695b1SPhilippe Mathieu-Daudé .is_enabled = is_fdc_enabled,
3626f6695b1SPhilippe Mathieu-Daudé .get_iobase = get_fdc_iobase,
3636f6695b1SPhilippe Mathieu-Daudé .get_irq = get_fdc_irq,
3646f6695b1SPhilippe Mathieu-Daudé };
365c16a4e1bSPhilippe Mathieu-Daudé sc->ide = (ISASuperIOFuncs){
366c16a4e1bSPhilippe Mathieu-Daudé .count = 1,
367c16a4e1bSPhilippe Mathieu-Daudé .is_enabled = is_ide_enabled,
368c16a4e1bSPhilippe Mathieu-Daudé .get_iobase = get_ide_iobase,
369c16a4e1bSPhilippe Mathieu-Daudé .get_irq = get_ide_irq,
370c16a4e1bSPhilippe Mathieu-Daudé };
37149ab747fSPaolo Bonzini }
37249ab747fSPaolo Bonzini
37349ab747fSPaolo Bonzini static const TypeInfo pc87312_type_info = {
374b3270669SEduardo Habkost .name = TYPE_PC87312,
37563f01a74SPhilippe Mathieu-Daudé .parent = TYPE_ISA_SUPERIO,
37649ab747fSPaolo Bonzini .instance_size = sizeof(PC87312State),
37749ab747fSPaolo Bonzini .instance_init = pc87312_initfn,
37849ab747fSPaolo Bonzini .class_init = pc87312_class_init,
3796f6695b1SPhilippe Mathieu-Daudé /* FIXME use a qdev drive property instead of drive_get() */
38049ab747fSPaolo Bonzini };
38149ab747fSPaolo Bonzini
pc87312_register_types(void)38249ab747fSPaolo Bonzini static void pc87312_register_types(void)
38349ab747fSPaolo Bonzini {
38449ab747fSPaolo Bonzini type_register_static(&pc87312_type_info);
38549ab747fSPaolo Bonzini }
38649ab747fSPaolo Bonzini
38749ab747fSPaolo Bonzini type_init(pc87312_register_types)
388