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" 329c17d615SPaolo Bonzini #include "sysemu/dma.h" 3371e8a915SMarkus Armbruster #include "sysemu/reset.h" 344c3df0ecSJuan Quintela 35a9c94277SMarkus Armbruster #include "hw/ide/pci.h" 363eee2611SJohn Snow #include "trace.h" 374c3df0ecSJuan Quintela 384c3df0ecSJuan Quintela /* CMD646 specific */ 395bbc0a70SMark Cave-Ayland #define CFR 0x50 405bbc0a70SMark Cave-Ayland #define CFR_INTR_CH0 0x04 4158f16a7bSMark Cave-Ayland #define CNTRL 0x51 4258f16a7bSMark Cave-Ayland #define CNTRL_EN_CH0 0x04 4358f16a7bSMark Cave-Ayland #define CNTRL_EN_CH1 0x08 445bbc0a70SMark Cave-Ayland #define ARTTIM23 0x57 455bbc0a70SMark Cave-Ayland #define ARTTIM23_INTR_CH1 0x10 464c3df0ecSJuan Quintela #define MRDMODE 0x71 474c3df0ecSJuan Quintela #define MRDMODE_INTR_CH0 0x04 484c3df0ecSJuan Quintela #define MRDMODE_INTR_CH1 0x08 494c3df0ecSJuan Quintela #define MRDMODE_BLK_CH0 0x10 504c3df0ecSJuan Quintela #define MRDMODE_BLK_CH1 0x20 514c3df0ecSJuan Quintela #define UDIDETCR0 0x73 524c3df0ecSJuan Quintela #define UDIDETCR1 0x7B 534c3df0ecSJuan Quintela 54dab91a1eSMark Cave-Ayland static void cmd646_update_irq(PCIDevice *pd); 554c3df0ecSJuan Quintela 565bbc0a70SMark Cave-Ayland static void cmd646_update_dma_interrupts(PCIDevice *pd) 575bbc0a70SMark Cave-Ayland { 585bbc0a70SMark Cave-Ayland /* Sync DMA interrupt status from UDMA interrupt status */ 595bbc0a70SMark Cave-Ayland if (pd->config[MRDMODE] & MRDMODE_INTR_CH0) { 605bbc0a70SMark Cave-Ayland pd->config[CFR] |= CFR_INTR_CH0; 615bbc0a70SMark Cave-Ayland } else { 625bbc0a70SMark Cave-Ayland pd->config[CFR] &= ~CFR_INTR_CH0; 635bbc0a70SMark Cave-Ayland } 645bbc0a70SMark Cave-Ayland 655bbc0a70SMark Cave-Ayland if (pd->config[MRDMODE] & MRDMODE_INTR_CH1) { 665bbc0a70SMark Cave-Ayland pd->config[ARTTIM23] |= ARTTIM23_INTR_CH1; 675bbc0a70SMark Cave-Ayland } else { 685bbc0a70SMark Cave-Ayland pd->config[ARTTIM23] &= ~ARTTIM23_INTR_CH1; 695bbc0a70SMark Cave-Ayland } 705bbc0a70SMark Cave-Ayland } 715bbc0a70SMark Cave-Ayland 72271dddd1SMark Cave-Ayland static void cmd646_update_udma_interrupts(PCIDevice *pd) 73271dddd1SMark Cave-Ayland { 74271dddd1SMark Cave-Ayland /* Sync UDMA interrupt status from DMA interrupt status */ 75271dddd1SMark Cave-Ayland if (pd->config[CFR] & CFR_INTR_CH0) { 76271dddd1SMark Cave-Ayland pd->config[MRDMODE] |= MRDMODE_INTR_CH0; 77271dddd1SMark Cave-Ayland } else { 78271dddd1SMark Cave-Ayland pd->config[MRDMODE] &= ~MRDMODE_INTR_CH0; 79271dddd1SMark Cave-Ayland } 80271dddd1SMark Cave-Ayland 81271dddd1SMark Cave-Ayland if (pd->config[ARTTIM23] & ARTTIM23_INTR_CH1) { 82271dddd1SMark Cave-Ayland pd->config[MRDMODE] |= MRDMODE_INTR_CH1; 83271dddd1SMark Cave-Ayland } else { 84271dddd1SMark Cave-Ayland pd->config[MRDMODE] &= ~MRDMODE_INTR_CH1; 85271dddd1SMark Cave-Ayland } 86271dddd1SMark Cave-Ayland } 87271dddd1SMark Cave-Ayland 88a8170e5eSAvi Kivity static uint64_t bmdma_read(void *opaque, hwaddr addr, 89a9deb8c6SAvi Kivity unsigned size) 90a9deb8c6SAvi Kivity { 91a9deb8c6SAvi Kivity BMDMAState *bm = opaque; 92f6c11d56SAndreas Färber PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); 934c3df0ecSJuan Quintela uint32_t val; 944c3df0ecSJuan Quintela 95a9deb8c6SAvi Kivity if (size != 1) { 96a9deb8c6SAvi Kivity return ((uint64_t)1 << (size * 8)) - 1; 97a9deb8c6SAvi Kivity } 98a9deb8c6SAvi Kivity 994c3df0ecSJuan Quintela switch(addr & 3) { 1004c3df0ecSJuan Quintela case 0: 1014c3df0ecSJuan Quintela val = bm->cmd; 1024c3df0ecSJuan Quintela break; 1034c3df0ecSJuan Quintela case 1: 104f6c11d56SAndreas Färber val = pci_dev->config[MRDMODE]; 1054c3df0ecSJuan Quintela break; 1064c3df0ecSJuan Quintela case 2: 1074c3df0ecSJuan Quintela val = bm->status; 1084c3df0ecSJuan Quintela break; 1094c3df0ecSJuan Quintela case 3: 110f6c11d56SAndreas Färber if (bm == &bm->pci_dev->bmdma[0]) { 111f6c11d56SAndreas Färber val = pci_dev->config[UDIDETCR0]; 1124c3df0ecSJuan Quintela } else { 113f6c11d56SAndreas Färber val = pci_dev->config[UDIDETCR1]; 1144c3df0ecSJuan Quintela } 1154c3df0ecSJuan Quintela break; 1164c3df0ecSJuan Quintela default: 1174c3df0ecSJuan Quintela val = 0xff; 1184c3df0ecSJuan Quintela break; 1194c3df0ecSJuan Quintela } 1203eee2611SJohn Snow 1213eee2611SJohn Snow trace_bmdma_read_cmd646(addr, val); 1224c3df0ecSJuan Quintela return val; 1234c3df0ecSJuan Quintela } 1244c3df0ecSJuan Quintela 125a8170e5eSAvi Kivity static void bmdma_write(void *opaque, hwaddr addr, 126a9deb8c6SAvi Kivity uint64_t val, unsigned size) 1274c3df0ecSJuan Quintela { 128a9deb8c6SAvi Kivity BMDMAState *bm = opaque; 129f6c11d56SAndreas Färber PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); 13070ae65f5SIgor V. Kovalenko 131a9deb8c6SAvi Kivity if (size != 1) { 132a9deb8c6SAvi Kivity return; 13370ae65f5SIgor V. Kovalenko } 13470ae65f5SIgor V. Kovalenko 1353eee2611SJohn Snow trace_bmdma_write_cmd646(addr, val); 1364c3df0ecSJuan Quintela switch(addr & 3) { 13750a48094SIgor V. Kovalenko case 0: 138a9deb8c6SAvi Kivity bmdma_cmd_writeb(bm, val); 13950a48094SIgor V. Kovalenko break; 1404c3df0ecSJuan Quintela case 1: 141f6c11d56SAndreas Färber pci_dev->config[MRDMODE] = 142f6c11d56SAndreas Färber (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30); 1435bbc0a70SMark Cave-Ayland cmd646_update_dma_interrupts(pci_dev); 144dab91a1eSMark Cave-Ayland cmd646_update_irq(pci_dev); 1454c3df0ecSJuan Quintela break; 1464c3df0ecSJuan Quintela case 2: 1474c3df0ecSJuan Quintela bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); 1484c3df0ecSJuan Quintela break; 1494c3df0ecSJuan Quintela case 3: 150f6c11d56SAndreas Färber if (bm == &bm->pci_dev->bmdma[0]) { 151f6c11d56SAndreas Färber pci_dev->config[UDIDETCR0] = val; 152f6c11d56SAndreas Färber } else { 153f6c11d56SAndreas Färber pci_dev->config[UDIDETCR1] = val; 154f6c11d56SAndreas Färber } 1554c3df0ecSJuan Quintela break; 1564c3df0ecSJuan Quintela } 1574c3df0ecSJuan Quintela } 1584c3df0ecSJuan Quintela 159a348f108SStefan Weil static const MemoryRegionOps cmd646_bmdma_ops = { 160a9deb8c6SAvi Kivity .read = bmdma_read, 161a9deb8c6SAvi Kivity .write = bmdma_write, 162a9deb8c6SAvi Kivity }; 163a9deb8c6SAvi Kivity 164a9deb8c6SAvi Kivity static void bmdma_setup_bar(PCIIDEState *d) 16570ae65f5SIgor V. Kovalenko { 166a9deb8c6SAvi Kivity BMDMAState *bm; 1674c3df0ecSJuan Quintela int i; 1684c3df0ecSJuan Quintela 1691437c94bSPaolo Bonzini memory_region_init(&d->bmdma_bar, OBJECT(d), "cmd646-bmdma", 16); 1704c3df0ecSJuan Quintela for(i = 0;i < 2; i++) { 171a9deb8c6SAvi Kivity bm = &d->bmdma[i]; 1721437c94bSPaolo Bonzini memory_region_init_io(&bm->extra_io, OBJECT(d), &cmd646_bmdma_ops, bm, 173a9deb8c6SAvi Kivity "cmd646-bmdma-bus", 4); 174a9deb8c6SAvi Kivity memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io); 1751437c94bSPaolo Bonzini memory_region_init_io(&bm->addr_ioport, OBJECT(d), 1761437c94bSPaolo Bonzini &bmdma_addr_ioport_ops, bm, 177a9deb8c6SAvi Kivity "cmd646-bmdma-ioport", 4); 178a9deb8c6SAvi Kivity memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport); 1794c3df0ecSJuan Quintela } 1804c3df0ecSJuan Quintela } 1814c3df0ecSJuan Quintela 182dab91a1eSMark Cave-Ayland static void cmd646_update_irq(PCIDevice *pd) 1834c3df0ecSJuan Quintela { 1844c3df0ecSJuan Quintela int pci_level; 185f6c11d56SAndreas Färber 186f6c11d56SAndreas Färber pci_level = ((pd->config[MRDMODE] & MRDMODE_INTR_CH0) && 187f6c11d56SAndreas Färber !(pd->config[MRDMODE] & MRDMODE_BLK_CH0)) || 188f6c11d56SAndreas Färber ((pd->config[MRDMODE] & MRDMODE_INTR_CH1) && 189f6c11d56SAndreas Färber !(pd->config[MRDMODE] & MRDMODE_BLK_CH1)); 1909e64f8a3SMarcel Apfelbaum pci_set_irq(pd, pci_level); 1914c3df0ecSJuan Quintela } 1924c3df0ecSJuan Quintela 1934c3df0ecSJuan Quintela /* the PCI irq level is the logical OR of the two channels */ 1944c3df0ecSJuan Quintela static void cmd646_set_irq(void *opaque, int channel, int level) 1954c3df0ecSJuan Quintela { 1964c3df0ecSJuan Quintela PCIIDEState *d = opaque; 197f6c11d56SAndreas Färber PCIDevice *pd = PCI_DEVICE(d); 1984c3df0ecSJuan Quintela int irq_mask; 1994c3df0ecSJuan Quintela 2004c3df0ecSJuan Quintela irq_mask = MRDMODE_INTR_CH0 << channel; 201f6c11d56SAndreas Färber if (level) { 202f6c11d56SAndreas Färber pd->config[MRDMODE] |= irq_mask; 203f6c11d56SAndreas Färber } else { 204f6c11d56SAndreas Färber pd->config[MRDMODE] &= ~irq_mask; 205f6c11d56SAndreas Färber } 2065bbc0a70SMark Cave-Ayland cmd646_update_dma_interrupts(pd); 207dab91a1eSMark Cave-Ayland cmd646_update_irq(pd); 2084c3df0ecSJuan Quintela } 2094c3df0ecSJuan Quintela 21051e5ba55SMark Cave-Ayland static void cmd646_reset(DeviceState *dev) 2114c3df0ecSJuan Quintela { 21251e5ba55SMark Cave-Ayland PCIIDEState *d = PCI_IDE(dev); 2134c3df0ecSJuan Quintela unsigned int i; 2144c3df0ecSJuan Quintela 2154a643563SBlue Swirl for (i = 0; i < 2; i++) { 2164a643563SBlue Swirl ide_bus_reset(&d->bus[i]); 2174a643563SBlue Swirl } 2184c3df0ecSJuan Quintela } 2194c3df0ecSJuan Quintela 2201d113ef8SMark Cave-Ayland static uint32_t cmd646_pci_config_read(PCIDevice *d, 2211d113ef8SMark Cave-Ayland uint32_t address, int len) 2221d113ef8SMark Cave-Ayland { 2231d113ef8SMark Cave-Ayland return pci_default_read_config(d, address, len); 2241d113ef8SMark Cave-Ayland } 2251d113ef8SMark Cave-Ayland 2261d113ef8SMark Cave-Ayland static void cmd646_pci_config_write(PCIDevice *d, uint32_t addr, uint32_t val, 2271d113ef8SMark Cave-Ayland int l) 2281d113ef8SMark Cave-Ayland { 2291d113ef8SMark Cave-Ayland uint32_t i; 2301d113ef8SMark Cave-Ayland 2311d113ef8SMark Cave-Ayland pci_default_write_config(d, addr, val, l); 2321d113ef8SMark Cave-Ayland 2331d113ef8SMark Cave-Ayland for (i = addr; i < addr + l; i++) { 2341d113ef8SMark Cave-Ayland switch (i) { 235271dddd1SMark Cave-Ayland case CFR: 236271dddd1SMark Cave-Ayland case ARTTIM23: 237271dddd1SMark Cave-Ayland cmd646_update_udma_interrupts(d); 238271dddd1SMark Cave-Ayland break; 2391d113ef8SMark Cave-Ayland case MRDMODE: 2401d113ef8SMark Cave-Ayland cmd646_update_dma_interrupts(d); 2411d113ef8SMark Cave-Ayland break; 2421d113ef8SMark Cave-Ayland } 2431d113ef8SMark Cave-Ayland } 2441d113ef8SMark Cave-Ayland 2451d113ef8SMark Cave-Ayland cmd646_update_irq(d); 2461d113ef8SMark Cave-Ayland } 2471d113ef8SMark Cave-Ayland 2484c3df0ecSJuan Quintela /* CMD646 PCI IDE controller */ 2499af21dbeSMarkus Armbruster static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp) 2504c3df0ecSJuan Quintela { 251f6c11d56SAndreas Färber PCIIDEState *d = PCI_IDE(dev); 252cbf4c9acSMark Cave-Ayland DeviceState *ds = DEVICE(dev); 253f6c11d56SAndreas Färber uint8_t *pci_conf = dev->config; 25461d9d6b0SStefan Hajnoczi int i; 2554c3df0ecSJuan Quintela 256409570a7SMichael S. Tsirkin pci_conf[PCI_CLASS_PROG] = 0x8f; 2574c3df0ecSJuan Quintela 25858f16a7bSMark Cave-Ayland pci_conf[CNTRL] = CNTRL_EN_CH0; // enable IDE0 2594c3df0ecSJuan Quintela if (d->secondary) { 2604c3df0ecSJuan Quintela /* XXX: if not enabled, really disable the seconday IDE controller */ 26158f16a7bSMark Cave-Ayland pci_conf[CNTRL] |= CNTRL_EN_CH1; /* enable IDE1 */ 2624c3df0ecSJuan Quintela } 2634c3df0ecSJuan Quintela 2641d113ef8SMark Cave-Ayland /* Set write-to-clear interrupt bits */ 265271dddd1SMark Cave-Ayland dev->wmask[CFR] = 0x0; 266271dddd1SMark Cave-Ayland dev->w1cmask[CFR] = CFR_INTR_CH0; 267271dddd1SMark Cave-Ayland dev->wmask[ARTTIM23] = 0x0; 268271dddd1SMark Cave-Ayland dev->w1cmask[ARTTIM23] = ARTTIM23_INTR_CH1; 2691d113ef8SMark Cave-Ayland dev->wmask[MRDMODE] = 0x0; 2701d113ef8SMark Cave-Ayland dev->w1cmask[MRDMODE] = MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1; 2711d113ef8SMark Cave-Ayland 2728ac98d1aSBALATON Zoltan memory_region_init_io(&d->data_bar[0], OBJECT(d), &pci_ide_data_le_ops, 2738ac98d1aSBALATON Zoltan &d->bus[0], "cmd646-data0", 8); 2748ac98d1aSBALATON Zoltan pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[0]); 2758ac98d1aSBALATON Zoltan 2768ac98d1aSBALATON Zoltan memory_region_init_io(&d->cmd_bar[0], OBJECT(d), &pci_ide_cmd_le_ops, 2778ac98d1aSBALATON Zoltan &d->bus[0], "cmd646-cmd0", 4); 2788ac98d1aSBALATON Zoltan pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[0]); 2798ac98d1aSBALATON Zoltan 2808ac98d1aSBALATON Zoltan memory_region_init_io(&d->data_bar[1], OBJECT(d), &pci_ide_data_le_ops, 2818ac98d1aSBALATON Zoltan &d->bus[1], "cmd646-data1", 8); 2828ac98d1aSBALATON Zoltan pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[1]); 2838ac98d1aSBALATON Zoltan 2848ac98d1aSBALATON Zoltan memory_region_init_io(&d->cmd_bar[1], OBJECT(d), &pci_ide_cmd_le_ops, 2858ac98d1aSBALATON Zoltan &d->bus[1], "cmd646-cmd1", 4); 2868ac98d1aSBALATON Zoltan pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[1]); 2878ac98d1aSBALATON Zoltan 288a9deb8c6SAvi Kivity bmdma_setup_bar(d); 289e824b2ccSAvi Kivity pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar); 2904c3df0ecSJuan Quintela 291409570a7SMichael S. Tsirkin /* TODO: RST# value should be 0 */ 292409570a7SMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 2934c3df0ecSJuan Quintela 294cbf4c9acSMark Cave-Ayland qdev_init_gpio_in(ds, cmd646_set_irq, 2); 29561d9d6b0SStefan Hajnoczi for (i = 0; i < 2; i++) { 296*82c74ac4SPeter Maydell ide_bus_init(&d->bus[i], sizeof(d->bus[i]), ds, i, 2); 297cbf4c9acSMark Cave-Ayland ide_init2(&d->bus[i], qdev_get_gpio_in(ds, i)); 29861d9d6b0SStefan Hajnoczi 299a9deb8c6SAvi Kivity bmdma_init(&d->bus[i], &d->bmdma[i], d); 300f56b18c0SKevin Wolf d->bmdma[i].bus = &d->bus[i]; 301f878c916SPaolo Bonzini ide_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 31640021f08SAnthony Liguori static Property cmd646_ide_properties[] = { 3174c3df0ecSJuan Quintela DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0), 3184c3df0ecSJuan Quintela DEFINE_PROP_END_OF_LIST(), 31940021f08SAnthony Liguori }; 32040021f08SAnthony Liguori 32140021f08SAnthony Liguori static void cmd646_ide_class_init(ObjectClass *klass, void *data) 32240021f08SAnthony Liguori { 32339bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 32440021f08SAnthony Liguori PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 32540021f08SAnthony Liguori 32651e5ba55SMark Cave-Ayland dc->reset = cmd646_reset; 32762b411bdSMark Cave-Ayland dc->vmsd = &vmstate_ide_pci; 3289af21dbeSMarkus Armbruster k->realize = pci_cmd646_ide_realize; 32940021f08SAnthony Liguori k->exit = pci_cmd646_ide_exitfn; 33040021f08SAnthony Liguori k->vendor_id = PCI_VENDOR_ID_CMD; 33140021f08SAnthony Liguori k->device_id = PCI_DEVICE_ID_CMD_646; 33240021f08SAnthony Liguori k->revision = 0x07; 33340021f08SAnthony Liguori k->class_id = PCI_CLASS_STORAGE_IDE; 3341d113ef8SMark Cave-Ayland k->config_read = cmd646_pci_config_read; 3351d113ef8SMark Cave-Ayland k->config_write = cmd646_pci_config_write; 3364f67d30bSMarc-André Lureau device_class_set_props(dc, cmd646_ide_properties); 33774623e73SLaurent Vivier set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 33840021f08SAnthony Liguori } 33940021f08SAnthony Liguori 3408c43a6f0SAndreas Färber static const TypeInfo cmd646_ide_info = { 34140021f08SAnthony Liguori .name = "cmd646-ide", 342f6c11d56SAndreas Färber .parent = TYPE_PCI_IDE, 34340021f08SAnthony Liguori .class_init = cmd646_ide_class_init, 3444c3df0ecSJuan Quintela }; 3454c3df0ecSJuan Quintela 34683f7d43aSAndreas Färber static void cmd646_ide_register_types(void) 3474c3df0ecSJuan Quintela { 34839bffca2SAnthony Liguori type_register_static(&cmd646_ide_info); 3494c3df0ecSJuan Quintela } 35083f7d43aSAndreas Färber 35183f7d43aSAndreas Färber type_init(cmd646_ide_register_types) 352