Statistics
| Branch: | Revision:

root / hw / ide / pci.c @ a4c75a21

History | View | Annotate | Download (6.7 kB)

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