1a9dd6604SBALATON Zoltan /*
2a9dd6604SBALATON Zoltan * QEMU SiI3112A PCI to Serial ATA Controller Emulation
3a9dd6604SBALATON Zoltan *
4a9dd6604SBALATON Zoltan * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
5a9dd6604SBALATON Zoltan *
6a9dd6604SBALATON Zoltan * This work is licensed under the terms of the GNU GPL, version 2 or later.
7a9dd6604SBALATON Zoltan * See the COPYING file in the top-level directory.
8a9dd6604SBALATON Zoltan *
9a9dd6604SBALATON Zoltan */
10a9dd6604SBALATON Zoltan
11a9dd6604SBALATON Zoltan /* For documentation on this and similar cards see:
12a9dd6604SBALATON Zoltan * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
13a9dd6604SBALATON Zoltan */
14a9dd6604SBALATON Zoltan
15d8e39b70SMarkus Armbruster #include "qemu/osdep.h"
16d8e39b70SMarkus Armbruster #include "hw/ide/pci.h"
170b8fa32fSMarkus Armbruster #include "qemu/module.h"
18a9dd6604SBALATON Zoltan #include "trace.h"
19db1015e9SEduardo Habkost #include "qom/object.h"
200316482eSPhilippe Mathieu-Daudé #include "ide-internal.h"
21a9dd6604SBALATON Zoltan
22a9dd6604SBALATON Zoltan #define TYPE_SII3112_PCI "sii3112"
238063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(SiI3112PCIState, SII3112_PCI)
24a9dd6604SBALATON Zoltan
25a9dd6604SBALATON Zoltan typedef struct SiI3112Regs {
26a9dd6604SBALATON Zoltan uint32_t confstat;
27a9dd6604SBALATON Zoltan uint32_t scontrol;
28a9dd6604SBALATON Zoltan uint16_t sien;
29a9dd6604SBALATON Zoltan uint8_t swdata;
30a9dd6604SBALATON Zoltan } SiI3112Regs;
31a9dd6604SBALATON Zoltan
32db1015e9SEduardo Habkost struct SiI3112PCIState {
33a9dd6604SBALATON Zoltan PCIIDEState i;
34a9dd6604SBALATON Zoltan MemoryRegion mmio;
35a9dd6604SBALATON Zoltan SiI3112Regs regs[2];
36db1015e9SEduardo Habkost };
37a9dd6604SBALATON Zoltan
38a9dd6604SBALATON Zoltan /* The sii3112_reg_read and sii3112_reg_write functions implement the
39a9dd6604SBALATON Zoltan * Internal Register Space - BAR5 (section 6.7 of the data sheet).
40a9dd6604SBALATON Zoltan */
41a9dd6604SBALATON Zoltan
sii3112_reg_read(void * opaque,hwaddr addr,unsigned int size)42a9dd6604SBALATON Zoltan static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
43a9dd6604SBALATON Zoltan unsigned int size)
44a9dd6604SBALATON Zoltan {
45a9dd6604SBALATON Zoltan SiI3112PCIState *d = opaque;
4622c9336dSPhilippe Mathieu-Daudé uint64_t val;
47a9dd6604SBALATON Zoltan
48a9dd6604SBALATON Zoltan switch (addr) {
49a9dd6604SBALATON Zoltan case 0x00:
50a9dd6604SBALATON Zoltan val = d->i.bmdma[0].cmd;
51a9dd6604SBALATON Zoltan break;
52a9dd6604SBALATON Zoltan case 0x01:
53a9dd6604SBALATON Zoltan val = d->regs[0].swdata;
54a9dd6604SBALATON Zoltan break;
55a9dd6604SBALATON Zoltan case 0x02:
56a9dd6604SBALATON Zoltan val = d->i.bmdma[0].status;
57a9dd6604SBALATON Zoltan break;
58a9dd6604SBALATON Zoltan case 0x03:
59a9dd6604SBALATON Zoltan val = 0;
60a9dd6604SBALATON Zoltan break;
61a9dd6604SBALATON Zoltan case 0x04 ... 0x07:
62a9dd6604SBALATON Zoltan val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
63a9dd6604SBALATON Zoltan break;
64a9dd6604SBALATON Zoltan case 0x08:
65a9dd6604SBALATON Zoltan val = d->i.bmdma[1].cmd;
66a9dd6604SBALATON Zoltan break;
67a9dd6604SBALATON Zoltan case 0x09:
68a9dd6604SBALATON Zoltan val = d->regs[1].swdata;
69a9dd6604SBALATON Zoltan break;
70a9dd6604SBALATON Zoltan case 0x0a:
71a9dd6604SBALATON Zoltan val = d->i.bmdma[1].status;
72a9dd6604SBALATON Zoltan break;
73a9dd6604SBALATON Zoltan case 0x0b:
74a9dd6604SBALATON Zoltan val = 0;
75a9dd6604SBALATON Zoltan break;
76a9dd6604SBALATON Zoltan case 0x0c ... 0x0f:
77a9dd6604SBALATON Zoltan val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
78a9dd6604SBALATON Zoltan break;
79a9dd6604SBALATON Zoltan case 0x10:
80a9dd6604SBALATON Zoltan val = d->i.bmdma[0].cmd;
81a9dd6604SBALATON Zoltan val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
82a9dd6604SBALATON Zoltan val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
83a9dd6604SBALATON Zoltan val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
843a14ba46SBALATON Zoltan val |= (uint32_t)d->i.bmdma[0].status << 16;
853a14ba46SBALATON Zoltan val |= (uint32_t)d->i.bmdma[1].status << 24;
86a9dd6604SBALATON Zoltan break;
87a9dd6604SBALATON Zoltan case 0x18:
88a9dd6604SBALATON Zoltan val = d->i.bmdma[1].cmd;
89a9dd6604SBALATON Zoltan val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
903a14ba46SBALATON Zoltan val |= (uint32_t)d->i.bmdma[1].status << 16;
91a9dd6604SBALATON Zoltan break;
92a9dd6604SBALATON Zoltan case 0x80 ... 0x87:
934eefdf7cSBALATON Zoltan val = pci_ide_data_le_ops.read(&d->i.bus[0], addr - 0x80, size);
94a9dd6604SBALATON Zoltan break;
95a9dd6604SBALATON Zoltan case 0x8a:
964eefdf7cSBALATON Zoltan val = pci_ide_cmd_le_ops.read(&d->i.bus[0], 2, size);
97a9dd6604SBALATON Zoltan break;
98a9dd6604SBALATON Zoltan case 0xa0:
99a9dd6604SBALATON Zoltan val = d->regs[0].confstat;
100a9dd6604SBALATON Zoltan break;
101a9dd6604SBALATON Zoltan case 0xc0 ... 0xc7:
1024eefdf7cSBALATON Zoltan val = pci_ide_data_le_ops.read(&d->i.bus[1], addr - 0xc0, size);
103a9dd6604SBALATON Zoltan break;
104a9dd6604SBALATON Zoltan case 0xca:
1054eefdf7cSBALATON Zoltan val = pci_ide_cmd_le_ops.read(&d->i.bus[1], 2, size);
106a9dd6604SBALATON Zoltan break;
107a9dd6604SBALATON Zoltan case 0xe0:
108a9dd6604SBALATON Zoltan val = d->regs[1].confstat;
109a9dd6604SBALATON Zoltan break;
110a9dd6604SBALATON Zoltan case 0x100:
111a9dd6604SBALATON Zoltan val = d->regs[0].scontrol;
112a9dd6604SBALATON Zoltan break;
113a9dd6604SBALATON Zoltan case 0x104:
114a9dd6604SBALATON Zoltan val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
115a9dd6604SBALATON Zoltan break;
116a9dd6604SBALATON Zoltan case 0x148:
1173a14ba46SBALATON Zoltan val = (uint32_t)d->regs[0].sien << 16;
118a9dd6604SBALATON Zoltan break;
119a9dd6604SBALATON Zoltan case 0x180:
120a9dd6604SBALATON Zoltan val = d->regs[1].scontrol;
121a9dd6604SBALATON Zoltan break;
122a9dd6604SBALATON Zoltan case 0x184:
123a9dd6604SBALATON Zoltan val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
124a9dd6604SBALATON Zoltan break;
125a9dd6604SBALATON Zoltan case 0x1c8:
1263a14ba46SBALATON Zoltan val = (uint32_t)d->regs[1].sien << 16;
127a9dd6604SBALATON Zoltan break;
128a9dd6604SBALATON Zoltan default:
129a9dd6604SBALATON Zoltan val = 0;
13022c9336dSPhilippe Mathieu-Daudé break;
131a9dd6604SBALATON Zoltan }
132a9dd6604SBALATON Zoltan trace_sii3112_read(size, addr, val);
133a9dd6604SBALATON Zoltan return val;
134a9dd6604SBALATON Zoltan }
135a9dd6604SBALATON Zoltan
sii3112_reg_write(void * opaque,hwaddr addr,uint64_t val,unsigned int size)136a9dd6604SBALATON Zoltan static void sii3112_reg_write(void *opaque, hwaddr addr,
137a9dd6604SBALATON Zoltan uint64_t val, unsigned int size)
138a9dd6604SBALATON Zoltan {
139a9dd6604SBALATON Zoltan SiI3112PCIState *d = opaque;
140a9dd6604SBALATON Zoltan
141a9dd6604SBALATON Zoltan trace_sii3112_write(size, addr, val);
142a9dd6604SBALATON Zoltan switch (addr) {
143a9dd6604SBALATON Zoltan case 0x00:
144a9dd6604SBALATON Zoltan case 0x10:
145a9dd6604SBALATON Zoltan bmdma_cmd_writeb(&d->i.bmdma[0], val);
146a9dd6604SBALATON Zoltan break;
147a9dd6604SBALATON Zoltan case 0x01:
148a9dd6604SBALATON Zoltan case 0x11:
149a9dd6604SBALATON Zoltan d->regs[0].swdata = val & 0x3f;
150a9dd6604SBALATON Zoltan break;
151a9dd6604SBALATON Zoltan case 0x02:
152a9dd6604SBALATON Zoltan case 0x12:
1535fe24213SBernhard Beschow bmdma_status_writeb(&d->i.bmdma[0], val);
154a9dd6604SBALATON Zoltan break;
155a9dd6604SBALATON Zoltan case 0x04 ... 0x07:
156a9dd6604SBALATON Zoltan bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
157a9dd6604SBALATON Zoltan break;
158a9dd6604SBALATON Zoltan case 0x08:
159a9dd6604SBALATON Zoltan case 0x18:
160a9dd6604SBALATON Zoltan bmdma_cmd_writeb(&d->i.bmdma[1], val);
161a9dd6604SBALATON Zoltan break;
162a9dd6604SBALATON Zoltan case 0x09:
163a9dd6604SBALATON Zoltan case 0x19:
164a9dd6604SBALATON Zoltan d->regs[1].swdata = val & 0x3f;
165a9dd6604SBALATON Zoltan break;
166a9dd6604SBALATON Zoltan case 0x0a:
167a9dd6604SBALATON Zoltan case 0x1a:
1685fe24213SBernhard Beschow bmdma_status_writeb(&d->i.bmdma[1], val);
169a9dd6604SBALATON Zoltan break;
170a9dd6604SBALATON Zoltan case 0x0c ... 0x0f:
171a9dd6604SBALATON Zoltan bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
172a9dd6604SBALATON Zoltan break;
173a9dd6604SBALATON Zoltan case 0x80 ... 0x87:
1744eefdf7cSBALATON Zoltan pci_ide_data_le_ops.write(&d->i.bus[0], addr - 0x80, val, size);
175a9dd6604SBALATON Zoltan break;
176a9dd6604SBALATON Zoltan case 0x8a:
1774eefdf7cSBALATON Zoltan pci_ide_cmd_le_ops.write(&d->i.bus[0], 2, val, size);
178a9dd6604SBALATON Zoltan break;
179a9dd6604SBALATON Zoltan case 0xc0 ... 0xc7:
1804eefdf7cSBALATON Zoltan pci_ide_data_le_ops.write(&d->i.bus[1], addr - 0xc0, val, size);
181a9dd6604SBALATON Zoltan break;
182a9dd6604SBALATON Zoltan case 0xca:
1834eefdf7cSBALATON Zoltan pci_ide_cmd_le_ops.write(&d->i.bus[1], 2, val, size);
184a9dd6604SBALATON Zoltan break;
185a9dd6604SBALATON Zoltan case 0x100:
186a9dd6604SBALATON Zoltan d->regs[0].scontrol = val & 0xfff;
187a9dd6604SBALATON Zoltan if (val & 1) {
188a9dd6604SBALATON Zoltan ide_bus_reset(&d->i.bus[0]);
189a9dd6604SBALATON Zoltan }
190a9dd6604SBALATON Zoltan break;
191a9dd6604SBALATON Zoltan case 0x148:
192a9dd6604SBALATON Zoltan d->regs[0].sien = (val >> 16) & 0x3eed;
193a9dd6604SBALATON Zoltan break;
194a9dd6604SBALATON Zoltan case 0x180:
195a9dd6604SBALATON Zoltan d->regs[1].scontrol = val & 0xfff;
196a9dd6604SBALATON Zoltan if (val & 1) {
197a9dd6604SBALATON Zoltan ide_bus_reset(&d->i.bus[1]);
198a9dd6604SBALATON Zoltan }
199a9dd6604SBALATON Zoltan break;
200a9dd6604SBALATON Zoltan case 0x1c8:
201a9dd6604SBALATON Zoltan d->regs[1].sien = (val >> 16) & 0x3eed;
202a9dd6604SBALATON Zoltan break;
203a9dd6604SBALATON Zoltan default:
20422c9336dSPhilippe Mathieu-Daudé break;
205a9dd6604SBALATON Zoltan }
206a9dd6604SBALATON Zoltan }
207a9dd6604SBALATON Zoltan
208a9dd6604SBALATON Zoltan static const MemoryRegionOps sii3112_reg_ops = {
209a9dd6604SBALATON Zoltan .read = sii3112_reg_read,
210a9dd6604SBALATON Zoltan .write = sii3112_reg_write,
211a9dd6604SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN,
212a9dd6604SBALATON Zoltan };
213a9dd6604SBALATON Zoltan
214a9dd6604SBALATON Zoltan /* the PCI irq level is the logical OR of the two channels */
sii3112_update_irq(SiI3112PCIState * s)215a9dd6604SBALATON Zoltan static void sii3112_update_irq(SiI3112PCIState *s)
216a9dd6604SBALATON Zoltan {
217a9dd6604SBALATON Zoltan int i, set = 0;
218a9dd6604SBALATON Zoltan
219a9dd6604SBALATON Zoltan for (i = 0; i < 2; i++) {
220a9dd6604SBALATON Zoltan set |= s->regs[i].confstat & (1UL << 11);
221a9dd6604SBALATON Zoltan }
222a9dd6604SBALATON Zoltan pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
223a9dd6604SBALATON Zoltan }
224a9dd6604SBALATON Zoltan
sii3112_set_irq(void * opaque,int channel,int level)225a9dd6604SBALATON Zoltan static void sii3112_set_irq(void *opaque, int channel, int level)
226a9dd6604SBALATON Zoltan {
227a9dd6604SBALATON Zoltan SiI3112PCIState *s = opaque;
228a9dd6604SBALATON Zoltan
229a9dd6604SBALATON Zoltan trace_sii3112_set_irq(channel, level);
230a9dd6604SBALATON Zoltan if (level) {
231a9dd6604SBALATON Zoltan s->regs[channel].confstat |= (1UL << 11);
232a9dd6604SBALATON Zoltan } else {
233a9dd6604SBALATON Zoltan s->regs[channel].confstat &= ~(1UL << 11);
234a9dd6604SBALATON Zoltan }
235a9dd6604SBALATON Zoltan
236a9dd6604SBALATON Zoltan sii3112_update_irq(s);
237a9dd6604SBALATON Zoltan }
238a9dd6604SBALATON Zoltan
sii3112_reset(DeviceState * dev)239d96c81f9SPhilippe Mathieu-Daudé static void sii3112_reset(DeviceState *dev)
240a9dd6604SBALATON Zoltan {
241d96c81f9SPhilippe Mathieu-Daudé SiI3112PCIState *s = SII3112_PCI(dev);
242a9dd6604SBALATON Zoltan int i;
243a9dd6604SBALATON Zoltan
244a9dd6604SBALATON Zoltan for (i = 0; i < 2; i++) {
245a9dd6604SBALATON Zoltan s->regs[i].confstat = 0x6515 << 16;
246a9dd6604SBALATON Zoltan ide_bus_reset(&s->i.bus[i]);
247a9dd6604SBALATON Zoltan }
248a9dd6604SBALATON Zoltan }
249a9dd6604SBALATON Zoltan
sii3112_pci_realize(PCIDevice * dev,Error ** errp)250a9dd6604SBALATON Zoltan static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
251a9dd6604SBALATON Zoltan {
252a9dd6604SBALATON Zoltan SiI3112PCIState *d = SII3112_PCI(dev);
253a9dd6604SBALATON Zoltan PCIIDEState *s = PCI_IDE(dev);
254d6ef883dSPeter Maydell DeviceState *ds = DEVICE(dev);
255a9dd6604SBALATON Zoltan MemoryRegion *mr;
256a9dd6604SBALATON Zoltan int i;
257a9dd6604SBALATON Zoltan
258a9dd6604SBALATON Zoltan pci_config_set_interrupt_pin(dev->config, 1);
259a9dd6604SBALATON Zoltan pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
260a9dd6604SBALATON Zoltan
261a9dd6604SBALATON Zoltan /* BAR5 is in PCI memory space */
262a9dd6604SBALATON Zoltan memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
263a9dd6604SBALATON Zoltan "sii3112.bar5", 0x200);
264a9dd6604SBALATON Zoltan pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
265a9dd6604SBALATON Zoltan
266a9dd6604SBALATON Zoltan /* BAR0-BAR4 are PCI I/O space aliases into BAR5 */
267a9dd6604SBALATON Zoltan mr = g_new(MemoryRegion, 1);
268a9dd6604SBALATON Zoltan memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
269a9dd6604SBALATON Zoltan pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
270a9dd6604SBALATON Zoltan mr = g_new(MemoryRegion, 1);
271a9dd6604SBALATON Zoltan memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
272a9dd6604SBALATON Zoltan pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
273a9dd6604SBALATON Zoltan mr = g_new(MemoryRegion, 1);
274a9dd6604SBALATON Zoltan memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
275a9dd6604SBALATON Zoltan pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
276a9dd6604SBALATON Zoltan mr = g_new(MemoryRegion, 1);
277a9dd6604SBALATON Zoltan memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
278a9dd6604SBALATON Zoltan pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
279a9dd6604SBALATON Zoltan mr = g_new(MemoryRegion, 1);
280a9dd6604SBALATON Zoltan memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
281a9dd6604SBALATON Zoltan pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
282a9dd6604SBALATON Zoltan
283d6ef883dSPeter Maydell qdev_init_gpio_in(ds, sii3112_set_irq, 2);
284a9dd6604SBALATON Zoltan for (i = 0; i < 2; i++) {
28582c74ac4SPeter Maydell ide_bus_init(&s->bus[i], sizeof(s->bus[i]), ds, i, 1);
286c9519630SPhilippe Mathieu-Daudé ide_bus_init_output_irq(&s->bus[i], qdev_get_gpio_in(ds, i));
287a9dd6604SBALATON Zoltan
288a9dd6604SBALATON Zoltan bmdma_init(&s->bus[i], &s->bmdma[i], s);
289e29b1246SPhilippe Mathieu-Daudé ide_bus_register_restart_cb(&s->bus[i]);
290a9dd6604SBALATON Zoltan }
291a9dd6604SBALATON Zoltan }
292a9dd6604SBALATON Zoltan
sii3112_pci_class_init(ObjectClass * klass,void * data)293a9dd6604SBALATON Zoltan static void sii3112_pci_class_init(ObjectClass *klass, void *data)
294a9dd6604SBALATON Zoltan {
295a9dd6604SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass);
296a9dd6604SBALATON Zoltan PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
297a9dd6604SBALATON Zoltan
298a9dd6604SBALATON Zoltan pd->vendor_id = 0x1095;
299a9dd6604SBALATON Zoltan pd->device_id = 0x3112;
300a9dd6604SBALATON Zoltan pd->class_id = PCI_CLASS_STORAGE_RAID;
301a9dd6604SBALATON Zoltan pd->revision = 1;
302a9dd6604SBALATON Zoltan pd->realize = sii3112_pci_realize;
303*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, sii3112_reset);
304a9dd6604SBALATON Zoltan dc->desc = "SiI3112A SATA controller";
305a9dd6604SBALATON Zoltan set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
306a9dd6604SBALATON Zoltan }
307a9dd6604SBALATON Zoltan
308a9dd6604SBALATON Zoltan static const TypeInfo sii3112_pci_info = {
309a9dd6604SBALATON Zoltan .name = TYPE_SII3112_PCI,
310a9dd6604SBALATON Zoltan .parent = TYPE_PCI_IDE,
311a9dd6604SBALATON Zoltan .instance_size = sizeof(SiI3112PCIState),
312a9dd6604SBALATON Zoltan .class_init = sii3112_pci_class_init,
313a9dd6604SBALATON Zoltan };
314a9dd6604SBALATON Zoltan
sii3112_register_types(void)315a9dd6604SBALATON Zoltan static void sii3112_register_types(void)
316a9dd6604SBALATON Zoltan {
317a9dd6604SBALATON Zoltan type_register_static(&sii3112_pci_info);
318a9dd6604SBALATON Zoltan }
319a9dd6604SBALATON Zoltan
320a9dd6604SBALATON Zoltan type_init(sii3112_register_types)
321