|
|
1.1 root 1: /*
2: * QEMU IDE Emulation: PCI Bus support.
3: *
4: * Copyright (c) 2003 Fabrice Bellard
5: * Copyright (c) 2006 Openedhand Ltd.
6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a copy
8: * of this software and associated documentation files (the "Software"), to deal
9: * in the Software without restriction, including without limitation the rights
10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11: * copies of the Software, and to permit persons to whom the Software is
12: * furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included in
15: * all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23: * THE SOFTWARE.
24: */
25: #include <hw/hw.h>
26: #include <hw/pc.h>
27: #include <hw/pci.h>
28: #include <hw/isa.h>
29: #include "block.h"
30: #include "block_int.h"
31: #include "sysemu.h"
32: #include "dma.h"
33:
34: #include <hw/ide/pci.h>
35:
36: void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
37: {
38: BMDMAState *bm = opaque;
39: #ifdef DEBUG_IDE
40: printf("%s: 0x%08x\n", __func__, val);
41: #endif
42: if (!(val & BM_CMD_START)) {
1.1.1.2 ! root 43: /*
! 44: * We can't cancel Scatter Gather DMA in the middle of the
! 45: * operation or a partial (not full) DMA transfer would reach
! 46: * the storage so we wait for completion instead (we beahve
! 47: * like if the DMA was completed by the time the guest trying
! 48: * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
! 49: * set).
! 50: *
! 51: * In the future we'll be able to safely cancel the I/O if the
! 52: * whole DMA operation will be submitted to disk with a single
! 53: * aio operation with preadv/pwritev.
! 54: */
! 55: if (bm->aiocb) {
! 56: qemu_aio_flush();
! 57: #ifdef DEBUG_IDE
! 58: if (bm->aiocb)
! 59: printf("ide_dma_cancel: aiocb still pending");
! 60: if (bm->status & BM_STATUS_DMAING)
! 61: printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
! 62: #endif
! 63: }
1.1 root 64: bm->cmd = val & 0x09;
65: } else {
66: if (!(bm->status & BM_STATUS_DMAING)) {
67: bm->status |= BM_STATUS_DMAING;
68: /* start dma transfer if possible */
69: if (bm->dma_cb)
70: bm->dma_cb(bm, 0);
71: }
72: bm->cmd = val & 0x09;
73: }
74: }
75:
76: uint32_t bmdma_addr_readb(void *opaque, uint32_t addr)
77: {
78: BMDMAState *bm = opaque;
79: uint32_t val;
80: val = (bm->addr >> ((addr & 3) * 8)) & 0xff;
81: #ifdef DEBUG_IDE
82: printf("%s: 0x%08x\n", __func__, val);
83: #endif
84: return val;
85: }
86:
87: void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val)
88: {
89: BMDMAState *bm = opaque;
90: int shift = (addr & 3) * 8;
91: #ifdef DEBUG_IDE
92: printf("%s: 0x%08x\n", __func__, val);
93: #endif
94: bm->addr &= ~(0xFF << shift);
95: bm->addr |= ((val & 0xFF) << shift) & ~3;
96: bm->cur_addr = bm->addr;
97: }
98:
99: uint32_t bmdma_addr_readw(void *opaque, uint32_t addr)
100: {
101: BMDMAState *bm = opaque;
102: uint32_t val;
103: val = (bm->addr >> ((addr & 3) * 8)) & 0xffff;
104: #ifdef DEBUG_IDE
105: printf("%s: 0x%08x\n", __func__, val);
106: #endif
107: return val;
108: }
109:
110: void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val)
111: {
112: BMDMAState *bm = opaque;
113: int shift = (addr & 3) * 8;
114: #ifdef DEBUG_IDE
115: printf("%s: 0x%08x\n", __func__, val);
116: #endif
117: bm->addr &= ~(0xFFFF << shift);
118: bm->addr |= ((val & 0xFFFF) << shift) & ~3;
119: bm->cur_addr = bm->addr;
120: }
121:
122: uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
123: {
124: BMDMAState *bm = opaque;
125: uint32_t val;
126: val = bm->addr;
127: #ifdef DEBUG_IDE
128: printf("%s: 0x%08x\n", __func__, val);
129: #endif
130: return val;
131: }
132:
133: void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
134: {
135: BMDMAState *bm = opaque;
136: #ifdef DEBUG_IDE
137: printf("%s: 0x%08x\n", __func__, val);
138: #endif
139: bm->addr = val & ~3;
140: bm->cur_addr = bm->addr;
141: }
142:
1.1.1.2 ! root 143: static bool ide_bmdma_current_needed(void *opaque)
! 144: {
! 145: BMDMAState *bm = opaque;
! 146:
! 147: return (bm->cur_prd_len != 0);
! 148: }
! 149:
! 150: static const VMStateDescription vmstate_bmdma_current = {
! 151: .name = "ide bmdma_current",
! 152: .version_id = 1,
! 153: .minimum_version_id = 1,
! 154: .minimum_version_id_old = 1,
! 155: .fields = (VMStateField []) {
! 156: VMSTATE_UINT32(cur_addr, BMDMAState),
! 157: VMSTATE_UINT32(cur_prd_last, BMDMAState),
! 158: VMSTATE_UINT32(cur_prd_addr, BMDMAState),
! 159: VMSTATE_UINT32(cur_prd_len, BMDMAState),
! 160: VMSTATE_END_OF_LIST()
! 161: }
! 162: };
! 163:
! 164:
1.1 root 165: static const VMStateDescription vmstate_bmdma = {
166: .name = "ide bmdma",
167: .version_id = 3,
168: .minimum_version_id = 0,
169: .minimum_version_id_old = 0,
170: .fields = (VMStateField []) {
171: VMSTATE_UINT8(cmd, BMDMAState),
172: VMSTATE_UINT8(status, BMDMAState),
173: VMSTATE_UINT32(addr, BMDMAState),
174: VMSTATE_INT64(sector_num, BMDMAState),
175: VMSTATE_UINT32(nsector, BMDMAState),
176: VMSTATE_UINT8(unit, BMDMAState),
177: VMSTATE_END_OF_LIST()
1.1.1.2 ! root 178: },
! 179: .subsections = (VMStateSubsection []) {
! 180: {
! 181: .vmsd = &vmstate_bmdma_current,
! 182: .needed = ide_bmdma_current_needed,
! 183: }, {
! 184: /* empty */
! 185: }
1.1 root 186: }
187: };
188:
189: static int ide_pci_post_load(void *opaque, int version_id)
190: {
191: PCIIDEState *d = opaque;
192: int i;
193:
194: for(i = 0; i < 2; i++) {
195: /* current versions always store 0/1, but older version
196: stored bigger values. We only need last bit */
197: d->bmdma[i].unit &= 1;
198: }
199: return 0;
200: }
201:
202: const VMStateDescription vmstate_ide_pci = {
203: .name = "ide",
204: .version_id = 3,
205: .minimum_version_id = 0,
206: .minimum_version_id_old = 0,
207: .post_load = ide_pci_post_load,
208: .fields = (VMStateField []) {
209: VMSTATE_PCI_DEVICE(dev, PCIIDEState),
210: VMSTATE_STRUCT_ARRAY(bmdma, PCIIDEState, 2, 0,
211: vmstate_bmdma, BMDMAState),
212: VMSTATE_IDE_BUS_ARRAY(bus, PCIIDEState, 2),
213: VMSTATE_IDE_DRIVES(bus[0].ifs, PCIIDEState),
214: VMSTATE_IDE_DRIVES(bus[1].ifs, PCIIDEState),
215: VMSTATE_END_OF_LIST()
216: }
217: };
218:
219: void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table)
220: {
221: PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
222: static const int bus[4] = { 0, 0, 1, 1 };
223: static const int unit[4] = { 0, 1, 0, 1 };
224: int i;
225:
226: for (i = 0; i < 4; i++) {
227: if (hd_table[i] == NULL)
228: continue;
229: ide_create_drive(d->bus+bus[i], unit[i], hd_table[i]);
230: }
231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.