1977e1244SGerd Hoffmann /* 2977e1244SGerd Hoffmann * QEMU IDE Emulation: PCI Bus support. 3977e1244SGerd Hoffmann * 4977e1244SGerd Hoffmann * Copyright (c) 2003 Fabrice Bellard 5977e1244SGerd Hoffmann * Copyright (c) 2006 Openedhand Ltd. 6977e1244SGerd Hoffmann * 7977e1244SGerd Hoffmann * Permission is hereby granted, free of charge, to any person obtaining a copy 8977e1244SGerd Hoffmann * of this software and associated documentation files (the "Software"), to deal 9977e1244SGerd Hoffmann * in the Software without restriction, including without limitation the rights 10977e1244SGerd Hoffmann * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11977e1244SGerd Hoffmann * copies of the Software, and to permit persons to whom the Software is 12977e1244SGerd Hoffmann * furnished to do so, subject to the following conditions: 13977e1244SGerd Hoffmann * 14977e1244SGerd Hoffmann * The above copyright notice and this permission notice shall be included in 15977e1244SGerd Hoffmann * all copies or substantial portions of the Software. 16977e1244SGerd Hoffmann * 17977e1244SGerd Hoffmann * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18977e1244SGerd Hoffmann * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19977e1244SGerd Hoffmann * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20977e1244SGerd Hoffmann * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21977e1244SGerd Hoffmann * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22977e1244SGerd Hoffmann * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23977e1244SGerd Hoffmann * THE SOFTWARE. 24977e1244SGerd Hoffmann */ 2559f2a787SGerd Hoffmann #include <hw/hw.h> 2659f2a787SGerd Hoffmann #include <hw/pc.h> 2759f2a787SGerd Hoffmann #include <hw/pci.h> 28feef3102SGerd Hoffmann #include <hw/isa.h> 29977e1244SGerd Hoffmann #include "block.h" 30977e1244SGerd Hoffmann #include "block_int.h" 31977e1244SGerd Hoffmann #include "sysemu.h" 32977e1244SGerd Hoffmann #include "dma.h" 3359f2a787SGerd Hoffmann 3465c0f135SJuan Quintela #include <hw/ide/pci.h> 35977e1244SGerd Hoffmann 363e7e1558SJuan Quintela void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) 37977e1244SGerd Hoffmann { 38977e1244SGerd Hoffmann BMDMAState *bm = opaque; 39977e1244SGerd Hoffmann #ifdef DEBUG_IDE 40977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 41977e1244SGerd Hoffmann #endif 42977e1244SGerd Hoffmann if (!(val & BM_CMD_START)) { 43977e1244SGerd Hoffmann /* XXX: do it better */ 44977e1244SGerd Hoffmann ide_dma_cancel(bm); 45977e1244SGerd Hoffmann bm->cmd = val & 0x09; 46977e1244SGerd Hoffmann } else { 47977e1244SGerd Hoffmann if (!(bm->status & BM_STATUS_DMAING)) { 48977e1244SGerd Hoffmann bm->status |= BM_STATUS_DMAING; 49977e1244SGerd Hoffmann /* start dma transfer if possible */ 50977e1244SGerd Hoffmann if (bm->dma_cb) 51977e1244SGerd Hoffmann bm->dma_cb(bm, 0); 52977e1244SGerd Hoffmann } 53977e1244SGerd Hoffmann bm->cmd = val & 0x09; 54977e1244SGerd Hoffmann } 55977e1244SGerd Hoffmann } 56977e1244SGerd Hoffmann 573e7e1558SJuan Quintela uint32_t bmdma_addr_readb(void *opaque, uint32_t addr) 58977e1244SGerd Hoffmann { 59977e1244SGerd Hoffmann BMDMAState *bm = opaque; 60977e1244SGerd Hoffmann uint32_t val; 61977e1244SGerd Hoffmann val = (bm->addr >> ((addr & 3) * 8)) & 0xff; 62977e1244SGerd Hoffmann #ifdef DEBUG_IDE 63977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 64977e1244SGerd Hoffmann #endif 65977e1244SGerd Hoffmann return val; 66977e1244SGerd Hoffmann } 67977e1244SGerd Hoffmann 683e7e1558SJuan Quintela void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val) 69977e1244SGerd Hoffmann { 70977e1244SGerd Hoffmann BMDMAState *bm = opaque; 71977e1244SGerd Hoffmann int shift = (addr & 3) * 8; 72977e1244SGerd Hoffmann #ifdef DEBUG_IDE 73977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 74977e1244SGerd Hoffmann #endif 75977e1244SGerd Hoffmann bm->addr &= ~(0xFF << shift); 76977e1244SGerd Hoffmann bm->addr |= ((val & 0xFF) << shift) & ~3; 77977e1244SGerd Hoffmann bm->cur_addr = bm->addr; 78977e1244SGerd Hoffmann } 79977e1244SGerd Hoffmann 803e7e1558SJuan Quintela uint32_t bmdma_addr_readw(void *opaque, uint32_t addr) 81977e1244SGerd Hoffmann { 82977e1244SGerd Hoffmann BMDMAState *bm = opaque; 83977e1244SGerd Hoffmann uint32_t val; 84977e1244SGerd Hoffmann val = (bm->addr >> ((addr & 3) * 8)) & 0xffff; 85977e1244SGerd Hoffmann #ifdef DEBUG_IDE 86977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 87977e1244SGerd Hoffmann #endif 88977e1244SGerd Hoffmann return val; 89977e1244SGerd Hoffmann } 90977e1244SGerd Hoffmann 913e7e1558SJuan Quintela void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val) 92977e1244SGerd Hoffmann { 93977e1244SGerd Hoffmann BMDMAState *bm = opaque; 94977e1244SGerd Hoffmann int shift = (addr & 3) * 8; 95977e1244SGerd Hoffmann #ifdef DEBUG_IDE 96977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 97977e1244SGerd Hoffmann #endif 98977e1244SGerd Hoffmann bm->addr &= ~(0xFFFF << shift); 99977e1244SGerd Hoffmann bm->addr |= ((val & 0xFFFF) << shift) & ~3; 100977e1244SGerd Hoffmann bm->cur_addr = bm->addr; 101977e1244SGerd Hoffmann } 102977e1244SGerd Hoffmann 1033e7e1558SJuan Quintela uint32_t bmdma_addr_readl(void *opaque, uint32_t addr) 104977e1244SGerd Hoffmann { 105977e1244SGerd Hoffmann BMDMAState *bm = opaque; 106977e1244SGerd Hoffmann uint32_t val; 107977e1244SGerd Hoffmann val = bm->addr; 108977e1244SGerd Hoffmann #ifdef DEBUG_IDE 109977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 110977e1244SGerd Hoffmann #endif 111977e1244SGerd Hoffmann return val; 112977e1244SGerd Hoffmann } 113977e1244SGerd Hoffmann 1143e7e1558SJuan Quintela void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val) 115977e1244SGerd Hoffmann { 116977e1244SGerd Hoffmann BMDMAState *bm = opaque; 117977e1244SGerd Hoffmann #ifdef DEBUG_IDE 118977e1244SGerd Hoffmann printf("%s: 0x%08x\n", __func__, val); 119977e1244SGerd Hoffmann #endif 120977e1244SGerd Hoffmann bm->addr = val & ~3; 121977e1244SGerd Hoffmann bm->cur_addr = bm->addr; 122977e1244SGerd Hoffmann } 123977e1244SGerd Hoffmann 124*407a4f30SJuan Quintela static const VMStateDescription vmstate_bmdma = { 125*407a4f30SJuan Quintela .name = "ide bmdma", 126*407a4f30SJuan Quintela .version_id = 3, 127*407a4f30SJuan Quintela .minimum_version_id = 0, 128*407a4f30SJuan Quintela .minimum_version_id_old = 0, 129*407a4f30SJuan Quintela .fields = (VMStateField []) { 130*407a4f30SJuan Quintela VMSTATE_UINT8(cmd, BMDMAState), 131*407a4f30SJuan Quintela VMSTATE_UINT8(status, BMDMAState), 132*407a4f30SJuan Quintela VMSTATE_UINT32(addr, BMDMAState), 133*407a4f30SJuan Quintela VMSTATE_INT64(sector_num, BMDMAState), 134*407a4f30SJuan Quintela VMSTATE_UINT32(nsector, BMDMAState), 135*407a4f30SJuan Quintela VMSTATE_UINT8(unit, BMDMAState), 136*407a4f30SJuan Quintela VMSTATE_END_OF_LIST() 137*407a4f30SJuan Quintela } 138*407a4f30SJuan Quintela }; 139*407a4f30SJuan Quintela 140*407a4f30SJuan Quintela static int ide_pci_post_load(void *opaque, int version_id) 141977e1244SGerd Hoffmann { 142977e1244SGerd Hoffmann PCIIDEState *d = opaque; 143977e1244SGerd Hoffmann int i; 144977e1244SGerd Hoffmann 145977e1244SGerd Hoffmann for(i = 0; i < 2; i++) { 146*407a4f30SJuan Quintela /* current versions always store 0/1, but older version 147*407a4f30SJuan Quintela stored bigger values. We only need last bit */ 148*407a4f30SJuan Quintela d->bmdma[i].unit &= 1; 149977e1244SGerd Hoffmann } 150977e1244SGerd Hoffmann return 0; 151977e1244SGerd Hoffmann } 152977e1244SGerd Hoffmann 153*407a4f30SJuan Quintela const VMStateDescription vmstate_ide_pci = { 154*407a4f30SJuan Quintela .name = "ide", 155*407a4f30SJuan Quintela .version_id = 3, 156*407a4f30SJuan Quintela .minimum_version_id = 0, 157*407a4f30SJuan Quintela .minimum_version_id_old = 0, 158*407a4f30SJuan Quintela .post_load = ide_pci_post_load, 159*407a4f30SJuan Quintela .fields = (VMStateField []) { 160*407a4f30SJuan Quintela VMSTATE_PCI_DEVICE(dev, PCIIDEState), 161*407a4f30SJuan Quintela VMSTATE_STRUCT_ARRAY(bmdma, PCIIDEState, 2, 0, 162*407a4f30SJuan Quintela vmstate_bmdma, BMDMAState), 163*407a4f30SJuan Quintela VMSTATE_IDE_BUS_ARRAY(bus, PCIIDEState, 2), 164*407a4f30SJuan Quintela VMSTATE_IDE_DRIVES(bus[0].ifs, PCIIDEState), 165*407a4f30SJuan Quintela VMSTATE_IDE_DRIVES(bus[1].ifs, PCIIDEState), 166*407a4f30SJuan Quintela VMSTATE_END_OF_LIST() 167*407a4f30SJuan Quintela } 168*407a4f30SJuan Quintela }; 169*407a4f30SJuan Quintela 1703e7e1558SJuan Quintela void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table) 171feef3102SGerd Hoffmann { 172feef3102SGerd Hoffmann PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); 173feef3102SGerd Hoffmann static const int bus[4] = { 0, 0, 1, 1 }; 174feef3102SGerd Hoffmann static const int unit[4] = { 0, 1, 0, 1 }; 175feef3102SGerd Hoffmann int i; 176feef3102SGerd Hoffmann 177feef3102SGerd Hoffmann for (i = 0; i < 4; i++) { 178feef3102SGerd Hoffmann if (hd_table[i] == NULL) 179feef3102SGerd Hoffmann continue; 1801f850f10SGerd Hoffmann ide_create_drive(d->bus+bus[i], unit[i], hd_table[i]); 181feef3102SGerd Hoffmann } 182feef3102SGerd Hoffmann } 183