14c3df0ecSJuan Quintela /* 24c3df0ecSJuan Quintela * QEMU IDE Emulation: PCI cmd646 support. 34c3df0ecSJuan Quintela * 44c3df0ecSJuan Quintela * Copyright (c) 2003 Fabrice Bellard 54c3df0ecSJuan Quintela * Copyright (c) 2006 Openedhand Ltd. 64c3df0ecSJuan Quintela * 74c3df0ecSJuan Quintela * Permission is hereby granted, free of charge, to any person obtaining a copy 84c3df0ecSJuan Quintela * of this software and associated documentation files (the "Software"), to deal 94c3df0ecSJuan Quintela * in the Software without restriction, including without limitation the rights 104c3df0ecSJuan Quintela * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 114c3df0ecSJuan Quintela * copies of the Software, and to permit persons to whom the Software is 124c3df0ecSJuan Quintela * furnished to do so, subject to the following conditions: 134c3df0ecSJuan Quintela * 144c3df0ecSJuan Quintela * The above copyright notice and this permission notice shall be included in 154c3df0ecSJuan Quintela * all copies or substantial portions of the Software. 164c3df0ecSJuan Quintela * 174c3df0ecSJuan Quintela * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 184c3df0ecSJuan Quintela * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 194c3df0ecSJuan Quintela * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 204c3df0ecSJuan Quintela * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 214c3df0ecSJuan Quintela * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 224c3df0ecSJuan Quintela * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 234c3df0ecSJuan Quintela * THE SOFTWARE. 244c3df0ecSJuan Quintela */ 250b8fa32fSMarkus Armbruster 2653239262SPeter Maydell #include "qemu/osdep.h" 27a9c94277SMarkus Armbruster #include "hw/pci/pci.h" 28a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 29d6454270SMarkus Armbruster #include "migration/vmstate.h" 300b8fa32fSMarkus Armbruster #include "qemu/module.h" 31a9c94277SMarkus Armbruster #include "hw/isa/isa.h" 3232cad1ffSPhilippe Mathieu-Daudé #include "system/dma.h" 3332cad1ffSPhilippe Mathieu-Daudé #include "system/reset.h" 344c3df0ecSJuan Quintela 35a9c94277SMarkus Armbruster #include "hw/ide/pci.h" 360316482eSPhilippe Mathieu-Daudé #include "ide-internal.h" 373eee2611SJohn Snow #include "trace.h" 384c3df0ecSJuan Quintela 394c3df0ecSJuan Quintela /* CMD646 specific */ 405bbc0a70SMark Cave-Ayland #define CFR 0x50 415bbc0a70SMark Cave-Ayland #define CFR_INTR_CH0 0x04 4258f16a7bSMark Cave-Ayland #define CNTRL 0x51 4358f16a7bSMark Cave-Ayland #define CNTRL_EN_CH0 0x04 4458f16a7bSMark Cave-Ayland #define CNTRL_EN_CH1 0x08 455bbc0a70SMark Cave-Ayland #define ARTTIM23 0x57 465bbc0a70SMark Cave-Ayland #define ARTTIM23_INTR_CH1 0x10 474c3df0ecSJuan Quintela #define MRDMODE 0x71 484c3df0ecSJuan Quintela #define MRDMODE_INTR_CH0 0x04 494c3df0ecSJuan Quintela #define MRDMODE_INTR_CH1 0x08 504c3df0ecSJuan Quintela #define MRDMODE_BLK_CH0 0x10 514c3df0ecSJuan Quintela #define MRDMODE_BLK_CH1 0x20 524c3df0ecSJuan Quintela #define UDIDETCR0 0x73 534c3df0ecSJuan Quintela #define UDIDETCR1 0x7B 544c3df0ecSJuan Quintela 55dab91a1eSMark Cave-Ayland static void cmd646_update_irq(PCIDevice *pd); 564c3df0ecSJuan Quintela 575bbc0a70SMark Cave-Ayland static void cmd646_update_dma_interrupts(PCIDevice *pd) 585bbc0a70SMark Cave-Ayland { 595bbc0a70SMark Cave-Ayland /* Sync DMA interrupt status from UDMA interrupt status */ 605bbc0a70SMark Cave-Ayland if (pd->config[MRDMODE] & MRDMODE_INTR_CH0) { 615bbc0a70SMark Cave-Ayland pd->config[CFR] |= CFR_INTR_CH0; 625bbc0a70SMark Cave-Ayland } else { 635bbc0a70SMark Cave-Ayland pd->config[CFR] &= ~CFR_INTR_CH0; 645bbc0a70SMark Cave-Ayland } 655bbc0a70SMark Cave-Ayland 665bbc0a70SMark Cave-Ayland if (pd->config[MRDMODE] & MRDMODE_INTR_CH1) { 675bbc0a70SMark Cave-Ayland pd->config[ARTTIM23] |= ARTTIM23_INTR_CH1; 685bbc0a70SMark Cave-Ayland } else { 695bbc0a70SMark Cave-Ayland pd->config[ARTTIM23] &= ~ARTTIM23_INTR_CH1; 705bbc0a70SMark Cave-Ayland } 715bbc0a70SMark Cave-Ayland } 725bbc0a70SMark Cave-Ayland 73271dddd1SMark Cave-Ayland static void cmd646_update_udma_interrupts(PCIDevice *pd) 74271dddd1SMark Cave-Ayland { 75271dddd1SMark Cave-Ayland /* Sync UDMA interrupt status from DMA interrupt status */ 76271dddd1SMark Cave-Ayland if (pd->config[CFR] & CFR_INTR_CH0) { 77271dddd1SMark Cave-Ayland pd->config[MRDMODE] |= MRDMODE_INTR_CH0; 78271dddd1SMark Cave-Ayland } else { 79271dddd1SMark Cave-Ayland pd->config[MRDMODE] &= ~MRDMODE_INTR_CH0; 80271dddd1SMark Cave-Ayland } 81271dddd1SMark Cave-Ayland 82271dddd1SMark Cave-Ayland if (pd->config[ARTTIM23] & ARTTIM23_INTR_CH1) { 83271dddd1SMark Cave-Ayland pd->config[MRDMODE] |= MRDMODE_INTR_CH1; 84271dddd1SMark Cave-Ayland } else { 85271dddd1SMark Cave-Ayland pd->config[MRDMODE] &= ~MRDMODE_INTR_CH1; 86271dddd1SMark Cave-Ayland } 87271dddd1SMark Cave-Ayland } 88271dddd1SMark Cave-Ayland 89a8170e5eSAvi Kivity static uint64_t bmdma_read(void *opaque, hwaddr addr, 90a9deb8c6SAvi Kivity unsigned size) 91a9deb8c6SAvi Kivity { 92a9deb8c6SAvi Kivity BMDMAState *bm = opaque; 93f6c11d56SAndreas Färber PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); 944c3df0ecSJuan Quintela uint32_t val; 954c3df0ecSJuan Quintela 96a9deb8c6SAvi Kivity if (size != 1) { 97a9deb8c6SAvi Kivity return ((uint64_t)1 << (size * 8)) - 1; 98a9deb8c6SAvi Kivity } 99a9deb8c6SAvi Kivity 1004c3df0ecSJuan Quintela switch(addr & 3) { 1014c3df0ecSJuan Quintela case 0: 1024c3df0ecSJuan Quintela val = bm->cmd; 1034c3df0ecSJuan Quintela break; 1044c3df0ecSJuan Quintela case 1: 105f6c11d56SAndreas Färber val = pci_dev->config[MRDMODE]; 1064c3df0ecSJuan Quintela break; 1074c3df0ecSJuan Quintela case 2: 1084c3df0ecSJuan Quintela val = bm->status; 1094c3df0ecSJuan Quintela break; 1104c3df0ecSJuan Quintela case 3: 111f6c11d56SAndreas Färber if (bm == &bm->pci_dev->bmdma[0]) { 112f6c11d56SAndreas Färber val = pci_dev->config[UDIDETCR0]; 1134c3df0ecSJuan Quintela } else { 114f6c11d56SAndreas Färber val = pci_dev->config[UDIDETCR1]; 1154c3df0ecSJuan Quintela } 1164c3df0ecSJuan Quintela break; 1174c3df0ecSJuan Quintela default: 1184c3df0ecSJuan Quintela val = 0xff; 1194c3df0ecSJuan Quintela break; 1204c3df0ecSJuan Quintela } 1213eee2611SJohn Snow 1223eee2611SJohn Snow trace_bmdma_read_cmd646(addr, val); 1234c3df0ecSJuan Quintela return val; 1244c3df0ecSJuan Quintela } 1254c3df0ecSJuan Quintela 126a8170e5eSAvi Kivity static void bmdma_write(void *opaque, hwaddr addr, 127a9deb8c6SAvi Kivity uint64_t val, unsigned size) 1284c3df0ecSJuan Quintela { 129a9deb8c6SAvi Kivity BMDMAState *bm = opaque; 130f6c11d56SAndreas Färber PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); 13170ae65f5SIgor V. Kovalenko 132a9deb8c6SAvi Kivity if (size != 1) { 133a9deb8c6SAvi Kivity return; 13470ae65f5SIgor V. Kovalenko } 13570ae65f5SIgor V. Kovalenko 1363eee2611SJohn Snow trace_bmdma_write_cmd646(addr, val); 1374c3df0ecSJuan Quintela switch(addr & 3) { 13850a48094SIgor V. Kovalenko case 0: 139a9deb8c6SAvi Kivity bmdma_cmd_writeb(bm, val); 14050a48094SIgor V. Kovalenko break; 1414c3df0ecSJuan Quintela case 1: 142f6c11d56SAndreas Färber pci_dev->config[MRDMODE] = 143f6c11d56SAndreas Färber (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30); 1445bbc0a70SMark Cave-Ayland cmd646_update_dma_interrupts(pci_dev); 145dab91a1eSMark Cave-Ayland cmd646_update_irq(pci_dev); 1464c3df0ecSJuan Quintela break; 1474c3df0ecSJuan Quintela case 2: 1485fe24213SBernhard Beschow bmdma_status_writeb(bm, val); 1494c3df0ecSJuan Quintela break; 1504c3df0ecSJuan Quintela case 3: 151f6c11d56SAndreas Färber if (bm == &bm->pci_dev->bmdma[0]) { 152f6c11d56SAndreas Färber pci_dev->config[UDIDETCR0] = val; 153f6c11d56SAndreas Färber } else { 154f6c11d56SAndreas Färber pci_dev->config[UDIDETCR1] = val; 155f6c11d56SAndreas Färber } 1564c3df0ecSJuan Quintela break; 1574c3df0ecSJuan Quintela } 1584c3df0ecSJuan Quintela } 1594c3df0ecSJuan Quintela 160a348f108SStefan Weil static const MemoryRegionOps cmd646_bmdma_ops = { 161a9deb8c6SAvi Kivity .read = bmdma_read, 162a9deb8c6SAvi Kivity .write = bmdma_write, 163a9deb8c6SAvi Kivity }; 164a9deb8c6SAvi Kivity 165a9deb8c6SAvi Kivity static void bmdma_setup_bar(PCIIDEState *d) 16670ae65f5SIgor V. Kovalenko { 167a9deb8c6SAvi Kivity BMDMAState *bm; 1684c3df0ecSJuan Quintela int i; 1694c3df0ecSJuan Quintela 1701437c94bSPaolo Bonzini memory_region_init(&d->bmdma_bar, OBJECT(d), "cmd646-bmdma", 16); 1714c3df0ecSJuan Quintela for(i = 0;i < 2; i++) { 172a9deb8c6SAvi Kivity bm = &d->bmdma[i]; 1731437c94bSPaolo Bonzini memory_region_init_io(&bm->extra_io, OBJECT(d), &cmd646_bmdma_ops, bm, 174a9deb8c6SAvi Kivity "cmd646-bmdma-bus", 4); 175a9deb8c6SAvi Kivity memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io); 1761437c94bSPaolo Bonzini memory_region_init_io(&bm->addr_ioport, OBJECT(d), 1771437c94bSPaolo Bonzini &bmdma_addr_ioport_ops, bm, 178a9deb8c6SAvi Kivity "cmd646-bmdma-ioport", 4); 179a9deb8c6SAvi Kivity memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport); 1804c3df0ecSJuan Quintela } 1814c3df0ecSJuan Quintela } 1824c3df0ecSJuan Quintela 183dab91a1eSMark Cave-Ayland static void cmd646_update_irq(PCIDevice *pd) 1844c3df0ecSJuan Quintela { 1854c3df0ecSJuan Quintela int pci_level; 186f6c11d56SAndreas Färber 187f6c11d56SAndreas Färber pci_level = ((pd->config[MRDMODE] & MRDMODE_INTR_CH0) && 188f6c11d56SAndreas Färber !(pd->config[MRDMODE] & MRDMODE_BLK_CH0)) || 189f6c11d56SAndreas Färber ((pd->config[MRDMODE] & MRDMODE_INTR_CH1) && 190f6c11d56SAndreas Färber !(pd->config[MRDMODE] & MRDMODE_BLK_CH1)); 1919e64f8a3SMarcel Apfelbaum pci_set_irq(pd, pci_level); 1924c3df0ecSJuan Quintela } 1934c3df0ecSJuan Quintela 1944c3df0ecSJuan Quintela /* the PCI irq level is the logical OR of the two channels */ 1954c3df0ecSJuan Quintela static void cmd646_set_irq(void *opaque, int channel, int level) 1964c3df0ecSJuan Quintela { 1974c3df0ecSJuan Quintela PCIIDEState *d = opaque; 198f6c11d56SAndreas Färber PCIDevice *pd = PCI_DEVICE(d); 1994c3df0ecSJuan Quintela int irq_mask; 2004c3df0ecSJuan Quintela 2014c3df0ecSJuan Quintela irq_mask = MRDMODE_INTR_CH0 << channel; 202f6c11d56SAndreas Färber if (level) { 203f6c11d56SAndreas Färber pd->config[MRDMODE] |= irq_mask; 204f6c11d56SAndreas Färber } else { 205f6c11d56SAndreas Färber pd->config[MRDMODE] &= ~irq_mask; 206f6c11d56SAndreas Färber } 2075bbc0a70SMark Cave-Ayland cmd646_update_dma_interrupts(pd); 208dab91a1eSMark Cave-Ayland cmd646_update_irq(pd); 2094c3df0ecSJuan Quintela } 2104c3df0ecSJuan Quintela 21151e5ba55SMark Cave-Ayland static void cmd646_reset(DeviceState *dev) 2124c3df0ecSJuan Quintela { 21351e5ba55SMark Cave-Ayland PCIIDEState *d = PCI_IDE(dev); 2144c3df0ecSJuan Quintela unsigned int i; 2154c3df0ecSJuan Quintela 2164a643563SBlue Swirl for (i = 0; i < 2; i++) { 2174a643563SBlue Swirl ide_bus_reset(&d->bus[i]); 2184a643563SBlue Swirl } 2194c3df0ecSJuan Quintela } 2204c3df0ecSJuan Quintela 2211d113ef8SMark Cave-Ayland static uint32_t cmd646_pci_config_read(PCIDevice *d, 2221d113ef8SMark Cave-Ayland uint32_t address, int len) 2231d113ef8SMark Cave-Ayland { 2241d113ef8SMark Cave-Ayland return pci_default_read_config(d, address, len); 2251d113ef8SMark Cave-Ayland } 2261d113ef8SMark Cave-Ayland 2271d113ef8SMark Cave-Ayland static void cmd646_pci_config_write(PCIDevice *d, uint32_t addr, uint32_t val, 2281d113ef8SMark Cave-Ayland int l) 2291d113ef8SMark Cave-Ayland { 2301d113ef8SMark Cave-Ayland uint32_t i; 2311d113ef8SMark Cave-Ayland 2321d113ef8SMark Cave-Ayland pci_default_write_config(d, addr, val, l); 2331d113ef8SMark Cave-Ayland 2341d113ef8SMark Cave-Ayland for (i = addr; i < addr + l; i++) { 2351d113ef8SMark Cave-Ayland switch (i) { 236271dddd1SMark Cave-Ayland case CFR: 237271dddd1SMark Cave-Ayland case ARTTIM23: 238271dddd1SMark Cave-Ayland cmd646_update_udma_interrupts(d); 239271dddd1SMark Cave-Ayland break; 2401d113ef8SMark Cave-Ayland case MRDMODE: 2411d113ef8SMark Cave-Ayland cmd646_update_dma_interrupts(d); 2421d113ef8SMark Cave-Ayland break; 2431d113ef8SMark Cave-Ayland } 2441d113ef8SMark Cave-Ayland } 2451d113ef8SMark Cave-Ayland 2461d113ef8SMark Cave-Ayland cmd646_update_irq(d); 2471d113ef8SMark Cave-Ayland } 2481d113ef8SMark Cave-Ayland 2494c3df0ecSJuan Quintela /* CMD646 PCI IDE controller */ 2509af21dbeSMarkus Armbruster static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp) 2514c3df0ecSJuan Quintela { 252f6c11d56SAndreas Färber PCIIDEState *d = PCI_IDE(dev); 253cbf4c9acSMark Cave-Ayland DeviceState *ds = DEVICE(dev); 254f6c11d56SAndreas Färber uint8_t *pci_conf = dev->config; 25561d9d6b0SStefan Hajnoczi int i; 2564c3df0ecSJuan Quintela 257409570a7SMichael S. Tsirkin pci_conf[PCI_CLASS_PROG] = 0x8f; 2584c3df0ecSJuan Quintela 25958f16a7bSMark Cave-Ayland pci_conf[CNTRL] = CNTRL_EN_CH0; // enable IDE0 2604c3df0ecSJuan Quintela if (d->secondary) { 261a980b95cSMichael Tokarev /* XXX: if not enabled, really disable the secondary IDE controller */ 26258f16a7bSMark Cave-Ayland pci_conf[CNTRL] |= CNTRL_EN_CH1; /* enable IDE1 */ 2634c3df0ecSJuan Quintela } 2644c3df0ecSJuan Quintela 2651d113ef8SMark Cave-Ayland /* Set write-to-clear interrupt bits */ 266271dddd1SMark Cave-Ayland dev->wmask[CFR] = 0x0; 267271dddd1SMark Cave-Ayland dev->w1cmask[CFR] = CFR_INTR_CH0; 268271dddd1SMark Cave-Ayland dev->wmask[ARTTIM23] = 0x0; 269271dddd1SMark Cave-Ayland dev->w1cmask[ARTTIM23] = ARTTIM23_INTR_CH1; 2701d113ef8SMark Cave-Ayland dev->wmask[MRDMODE] = 0x0; 2711d113ef8SMark Cave-Ayland dev->w1cmask[MRDMODE] = MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1; 2721d113ef8SMark Cave-Ayland 2738ac98d1aSBALATON Zoltan memory_region_init_io(&d->data_bar[0], OBJECT(d), &pci_ide_data_le_ops, 2748ac98d1aSBALATON Zoltan &d->bus[0], "cmd646-data0", 8); 2758ac98d1aSBALATON Zoltan pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[0]); 2768ac98d1aSBALATON Zoltan 2778ac98d1aSBALATON Zoltan memory_region_init_io(&d->cmd_bar[0], OBJECT(d), &pci_ide_cmd_le_ops, 2788ac98d1aSBALATON Zoltan &d->bus[0], "cmd646-cmd0", 4); 2798ac98d1aSBALATON Zoltan pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[0]); 2808ac98d1aSBALATON Zoltan 2818ac98d1aSBALATON Zoltan memory_region_init_io(&d->data_bar[1], OBJECT(d), &pci_ide_data_le_ops, 2828ac98d1aSBALATON Zoltan &d->bus[1], "cmd646-data1", 8); 2838ac98d1aSBALATON Zoltan pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[1]); 2848ac98d1aSBALATON Zoltan 2858ac98d1aSBALATON Zoltan memory_region_init_io(&d->cmd_bar[1], OBJECT(d), &pci_ide_cmd_le_ops, 2868ac98d1aSBALATON Zoltan &d->bus[1], "cmd646-cmd1", 4); 2878ac98d1aSBALATON Zoltan pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[1]); 2888ac98d1aSBALATON Zoltan 289a9deb8c6SAvi Kivity bmdma_setup_bar(d); 290e824b2ccSAvi Kivity pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar); 2914c3df0ecSJuan Quintela 292409570a7SMichael S. Tsirkin /* TODO: RST# value should be 0 */ 293409570a7SMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 2944c3df0ecSJuan Quintela 295cbf4c9acSMark Cave-Ayland qdev_init_gpio_in(ds, cmd646_set_irq, 2); 29661d9d6b0SStefan Hajnoczi for (i = 0; i < 2; i++) { 29782c74ac4SPeter Maydell ide_bus_init(&d->bus[i], sizeof(d->bus[i]), ds, i, 2); 298c9519630SPhilippe Mathieu-Daudé ide_bus_init_output_irq(&d->bus[i], qdev_get_gpio_in(ds, i)); 29961d9d6b0SStefan Hajnoczi 300a9deb8c6SAvi Kivity bmdma_init(&d->bus[i], &d->bmdma[i], d); 301e29b1246SPhilippe Mathieu-Daudé ide_bus_register_restart_cb(&d->bus[i]); 30261d9d6b0SStefan Hajnoczi } 3034c3df0ecSJuan Quintela } 3044c3df0ecSJuan Quintela 305f90c2bcdSAlex Williamson static void pci_cmd646_ide_exitfn(PCIDevice *dev) 306a9deb8c6SAvi Kivity { 307f6c11d56SAndreas Färber PCIIDEState *d = PCI_IDE(dev); 308a9deb8c6SAvi Kivity unsigned i; 309a9deb8c6SAvi Kivity 310a9deb8c6SAvi Kivity for (i = 0; i < 2; ++i) { 311a9deb8c6SAvi Kivity memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io); 312a9deb8c6SAvi Kivity memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport); 313a9deb8c6SAvi Kivity } 314a9deb8c6SAvi Kivity } 315a9deb8c6SAvi Kivity 316aaa1f1a5SRichard Henderson static const Property cmd646_ide_properties[] = { 3174c3df0ecSJuan Quintela DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0), 31840021f08SAnthony Liguori }; 31940021f08SAnthony Liguori 320*12d1a768SPhilippe Mathieu-Daudé static void cmd646_ide_class_init(ObjectClass *klass, const void *data) 32140021f08SAnthony Liguori { 32239bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 32340021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 32440021f08SAnthony Liguori 325e3d08143SPeter Maydell device_class_set_legacy_reset(dc, cmd646_reset); 32662b411bdSMark Cave-Ayland dc->vmsd = &vmstate_ide_pci; 3279af21dbeSMarkus Armbruster k->realize = pci_cmd646_ide_realize; 32840021f08SAnthony Liguori k->exit = pci_cmd646_ide_exitfn; 32940021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_CMD; 33040021f08SAnthony Liguori k->device_id = PCI_DEVICE_ID_CMD_646; 33140021f08SAnthony Liguori k->revision = 0x07; 33240021f08SAnthony Liguori k->class_id = PCI_CLASS_STORAGE_IDE; 3331d113ef8SMark Cave-Ayland k->config_read = cmd646_pci_config_read; 3341d113ef8SMark Cave-Ayland k->config_write = cmd646_pci_config_write; 3354f67d30bSMarc-André Lureau device_class_set_props(dc, cmd646_ide_properties); 33674623e73SLaurent Vivier set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 33740021f08SAnthony Liguori } 33840021f08SAnthony Liguori 3398c43a6f0SAndreas Färber static const TypeInfo cmd646_ide_info = { 34040021f08SAnthony Liguori .name = "cmd646-ide", 341f6c11d56SAndreas Färber .parent = TYPE_PCI_IDE, 34240021f08SAnthony Liguori .class_init = cmd646_ide_class_init, 3434c3df0ecSJuan Quintela }; 3444c3df0ecSJuan Quintela 34583f7d43aSAndreas Färber static void cmd646_ide_register_types(void) 3464c3df0ecSJuan Quintela { 34739bffca2SAnthony Liguori type_register_static(&cmd646_ide_info); 3484c3df0ecSJuan Quintela } 34983f7d43aSAndreas Färber 35083f7d43aSAndreas Färber type_init(cmd646_ide_register_types) 351