~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to hw/ide/pci.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "dma.h"
 
31
 
 
32
#include <hw/ide/pci.h>
 
33
 
 
34
#define BMDMA_PAGE_SIZE 4096
 
35
 
 
36
static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
 
37
                            BlockDriverCompletionFunc *dma_cb)
 
38
{
 
39
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
40
 
 
41
    bm->unit = s->unit;
 
42
    bm->dma_cb = dma_cb;
 
43
    bm->cur_prd_last = 0;
 
44
    bm->cur_prd_addr = 0;
 
45
    bm->cur_prd_len = 0;
 
46
    bm->sector_num = ide_get_sector(s);
 
47
    bm->nsector = s->nsector;
 
48
 
 
49
    if (bm->status & BM_STATUS_DMAING) {
 
50
        bm->dma_cb(bmdma_active_if(bm), 0);
 
51
    }
 
52
}
 
53
 
 
54
/* return 0 if buffer completed */
 
55
static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
 
56
{
 
57
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
58
    IDEState *s = bmdma_active_if(bm);
 
59
    struct {
 
60
        uint32_t addr;
 
61
        uint32_t size;
 
62
    } prd;
 
63
    int l, len;
 
64
 
 
65
    pci_dma_sglist_init(&s->sg, &bm->pci_dev->dev,
 
66
                        s->nsector / (BMDMA_PAGE_SIZE / 512) + 1);
 
67
    s->io_buffer_size = 0;
 
68
    for(;;) {
 
69
        if (bm->cur_prd_len == 0) {
 
70
            /* end of table (with a fail safe of one page) */
 
71
            if (bm->cur_prd_last ||
 
72
                (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
 
73
                return s->io_buffer_size != 0;
 
74
            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
 
75
            bm->cur_addr += 8;
 
76
            prd.addr = le32_to_cpu(prd.addr);
 
77
            prd.size = le32_to_cpu(prd.size);
 
78
            len = prd.size & 0xfffe;
 
79
            if (len == 0)
 
80
                len = 0x10000;
 
81
            bm->cur_prd_len = len;
 
82
            bm->cur_prd_addr = prd.addr;
 
83
            bm->cur_prd_last = (prd.size & 0x80000000);
 
84
        }
 
85
        l = bm->cur_prd_len;
 
86
        if (l > 0) {
 
87
            qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
 
88
            bm->cur_prd_addr += l;
 
89
            bm->cur_prd_len -= l;
 
90
            s->io_buffer_size += l;
 
91
        }
 
92
    }
 
93
    return 1;
 
94
}
 
95
 
 
96
/* return 0 if buffer completed */
 
97
static int bmdma_rw_buf(IDEDMA *dma, int is_write)
 
98
{
 
99
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
100
    IDEState *s = bmdma_active_if(bm);
 
101
    struct {
 
102
        uint32_t addr;
 
103
        uint32_t size;
 
104
    } prd;
 
105
    int l, len;
 
106
 
 
107
    for(;;) {
 
108
        l = s->io_buffer_size - s->io_buffer_index;
 
109
        if (l <= 0)
 
110
            break;
 
111
        if (bm->cur_prd_len == 0) {
 
112
            /* end of table (with a fail safe of one page) */
 
113
            if (bm->cur_prd_last ||
 
114
                (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
 
115
                return 0;
 
116
            pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8);
 
117
            bm->cur_addr += 8;
 
118
            prd.addr = le32_to_cpu(prd.addr);
 
119
            prd.size = le32_to_cpu(prd.size);
 
120
            len = prd.size & 0xfffe;
 
121
            if (len == 0)
 
122
                len = 0x10000;
 
123
            bm->cur_prd_len = len;
 
124
            bm->cur_prd_addr = prd.addr;
 
125
            bm->cur_prd_last = (prd.size & 0x80000000);
 
126
        }
 
127
        if (l > bm->cur_prd_len)
 
128
            l = bm->cur_prd_len;
 
129
        if (l > 0) {
 
130
            if (is_write) {
 
131
                pci_dma_write(&bm->pci_dev->dev, bm->cur_prd_addr,
 
132
                              s->io_buffer + s->io_buffer_index, l);
 
133
            } else {
 
134
                pci_dma_read(&bm->pci_dev->dev, bm->cur_prd_addr,
 
135
                             s->io_buffer + s->io_buffer_index, l);
 
136
            }
 
137
            bm->cur_prd_addr += l;
 
138
            bm->cur_prd_len -= l;
 
139
            s->io_buffer_index += l;
 
140
        }
 
141
    }
 
142
    return 1;
 
143
}
 
144
 
 
145
static int bmdma_set_unit(IDEDMA *dma, int unit)
 
146
{
 
147
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
148
    bm->unit = unit;
 
149
 
 
150
    return 0;
 
151
}
 
152
 
 
153
static int bmdma_add_status(IDEDMA *dma, int status)
 
154
{
 
155
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
156
    bm->status |= status;
 
157
 
 
158
    return 0;
 
159
}
 
160
 
 
161
static int bmdma_set_inactive(IDEDMA *dma)
 
162
{
 
163
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
164
 
 
165
    bm->status &= ~BM_STATUS_DMAING;
 
166
    bm->dma_cb = NULL;
 
167
    bm->unit = -1;
 
168
 
 
169
    return 0;
 
170
}
 
171
 
 
172
static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd)
 
173
{
 
174
    IDEState *s = bmdma_active_if(bm);
 
175
 
 
176
    ide_set_sector(s, bm->sector_num);
 
177
    s->io_buffer_index = 0;
 
178
    s->io_buffer_size = 0;
 
179
    s->nsector = bm->nsector;
 
180
    s->dma_cmd = dma_cmd;
 
181
    bm->cur_addr = bm->addr;
 
182
    bm->dma_cb = ide_dma_cb;
 
183
    bmdma_start_dma(&bm->dma, s, bm->dma_cb);
 
184
}
 
185
 
 
186
/* TODO This should be common IDE code */
 
187
static void bmdma_restart_bh(void *opaque)
 
188
{
 
189
    BMDMAState *bm = opaque;
 
190
    IDEBus *bus = bm->bus;
 
191
    int is_read;
 
192
    int error_status;
 
193
 
 
194
    qemu_bh_delete(bm->bh);
 
195
    bm->bh = NULL;
 
196
 
 
197
    if (bm->unit == (uint8_t) -1) {
 
198
        return;
 
199
    }
 
200
 
 
201
    is_read = !!(bus->error_status & BM_STATUS_RETRY_READ);
 
202
 
 
203
    /* The error status must be cleared before resubmitting the request: The
 
204
     * request may fail again, and this case can only be distinguished if the
 
205
     * called function can set a new error status. */
 
206
    error_status = bus->error_status;
 
207
    bus->error_status = 0;
 
208
 
 
209
    if (error_status & BM_STATUS_DMA_RETRY) {
 
210
        if (error_status & BM_STATUS_RETRY_TRIM) {
 
211
            bmdma_restart_dma(bm, IDE_DMA_TRIM);
 
212
        } else {
 
213
            bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
 
214
        }
 
215
    } else if (error_status & BM_STATUS_PIO_RETRY) {
 
216
        if (is_read) {
 
217
            ide_sector_read(bmdma_active_if(bm));
 
218
        } else {
 
219
            ide_sector_write(bmdma_active_if(bm));
 
220
        }
 
221
    } else if (error_status & BM_STATUS_RETRY_FLUSH) {
 
222
        ide_flush_cache(bmdma_active_if(bm));
 
223
    }
 
224
}
 
225
 
 
226
static void bmdma_restart_cb(void *opaque, int running, RunState state)
 
227
{
 
228
    IDEDMA *dma = opaque;
 
229
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
230
 
 
231
    if (!running)
 
232
        return;
 
233
 
 
234
    if (!bm->bh) {
 
235
        bm->bh = qemu_bh_new(bmdma_restart_bh, &bm->dma);
 
236
        qemu_bh_schedule(bm->bh);
 
237
    }
 
238
}
 
239
 
 
240
static void bmdma_cancel(BMDMAState *bm)
 
241
{
 
242
    if (bm->status & BM_STATUS_DMAING) {
 
243
        /* cancel DMA request */
 
244
        bmdma_set_inactive(&bm->dma);
 
245
    }
 
246
}
 
247
 
 
248
static int bmdma_reset(IDEDMA *dma)
 
249
{
 
250
    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
251
 
 
252
#ifdef DEBUG_IDE
 
253
    printf("ide: dma_reset\n");
 
254
#endif
 
255
    bmdma_cancel(bm);
 
256
    bm->cmd = 0;
 
257
    bm->status = 0;
 
258
    bm->addr = 0;
 
259
    bm->cur_addr = 0;
 
260
    bm->cur_prd_last = 0;
 
261
    bm->cur_prd_addr = 0;
 
262
    bm->cur_prd_len = 0;
 
263
    bm->sector_num = 0;
 
264
    bm->nsector = 0;
 
265
 
 
266
    return 0;
 
267
}
 
268
 
 
269
static int bmdma_start_transfer(IDEDMA *dma)
 
270
{
 
271
    return 0;
 
272
}
 
273
 
 
274
static void bmdma_irq(void *opaque, int n, int level)
 
275
{
 
276
    BMDMAState *bm = opaque;
 
277
 
 
278
    if (!level) {
 
279
        /* pass through lower */
 
280
        qemu_set_irq(bm->irq, level);
 
281
        return;
 
282
    }
 
283
 
 
284
    bm->status |= BM_STATUS_INT;
 
285
 
 
286
    /* trigger the real irq */
 
287
    qemu_set_irq(bm->irq, level);
 
288
}
 
289
 
 
290
void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
 
291
{
 
292
#ifdef DEBUG_IDE
 
293
    printf("%s: 0x%08x\n", __func__, val);
 
294
#endif
 
295
 
 
296
    /* Ignore writes to SSBM if it keeps the old value */
 
297
    if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
 
298
        if (!(val & BM_CMD_START)) {
 
299
            /*
 
300
             * We can't cancel Scatter Gather DMA in the middle of the
 
301
             * operation or a partial (not full) DMA transfer would reach
 
302
             * the storage so we wait for completion instead (we beahve
 
303
             * like if the DMA was completed by the time the guest trying
 
304
             * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
 
305
             * set).
 
306
             *
 
307
             * In the future we'll be able to safely cancel the I/O if the
 
308
             * whole DMA operation will be submitted to disk with a single
 
309
             * aio operation with preadv/pwritev.
 
310
             */
 
311
            if (bm->bus->dma->aiocb) {
 
312
                qemu_aio_flush();
 
313
                assert(bm->bus->dma->aiocb == NULL);
 
314
                assert((bm->status & BM_STATUS_DMAING) == 0);
 
315
            }
 
316
        } else {
 
317
            bm->cur_addr = bm->addr;
 
318
            if (!(bm->status & BM_STATUS_DMAING)) {
 
319
                bm->status |= BM_STATUS_DMAING;
 
320
                /* start dma transfer if possible */
 
321
                if (bm->dma_cb)
 
322
                    bm->dma_cb(bmdma_active_if(bm), 0);
 
323
            }
 
324
        }
 
325
    }
 
326
 
 
327
    bm->cmd = val & 0x09;
 
328
}
 
329
 
 
330
static uint64_t bmdma_addr_read(void *opaque, dma_addr_t addr,
 
331
                                unsigned width)
 
332
{
 
333
    BMDMAState *bm = opaque;
 
334
    uint32_t mask = (1ULL << (width * 8)) - 1;
 
335
    uint64_t data;
 
336
 
 
337
    data = (bm->addr >> (addr * 8)) & mask;
 
338
#ifdef DEBUG_IDE
 
339
    printf("%s: 0x%08x\n", __func__, (unsigned)*data);
 
340
#endif
 
341
    return data;
 
342
}
 
343
 
 
344
static void bmdma_addr_write(void *opaque, dma_addr_t addr,
 
345
                             uint64_t data, unsigned width)
 
346
{
 
347
    BMDMAState *bm = opaque;
 
348
    int shift = addr * 8;
 
349
    uint32_t mask = (1ULL << (width * 8)) - 1;
 
350
 
 
351
#ifdef DEBUG_IDE
 
352
    printf("%s: 0x%08x\n", __func__, (unsigned)data);
 
353
#endif
 
354
    bm->addr &= ~(mask << shift);
 
355
    bm->addr |= ((data & mask) << shift) & ~3;
 
356
}
 
357
 
 
358
MemoryRegionOps bmdma_addr_ioport_ops = {
 
359
    .read = bmdma_addr_read,
 
360
    .write = bmdma_addr_write,
 
361
    .endianness = DEVICE_LITTLE_ENDIAN,
 
362
};
 
363
 
 
364
static bool ide_bmdma_current_needed(void *opaque)
 
365
{
 
366
    BMDMAState *bm = opaque;
 
367
 
 
368
    return (bm->cur_prd_len != 0);
 
369
}
 
370
 
 
371
static bool ide_bmdma_status_needed(void *opaque)
 
372
{
 
373
    BMDMAState *bm = opaque;
 
374
 
 
375
    /* Older versions abused some bits in the status register for internal
 
376
     * error state. If any of these bits are set, we must add a subsection to
 
377
     * transfer the real status register */
 
378
    uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS;
 
379
 
 
380
    return ((bm->status & abused_bits) != 0);
 
381
}
 
382
 
 
383
static void ide_bmdma_pre_save(void *opaque)
 
384
{
 
385
    BMDMAState *bm = opaque;
 
386
    uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS;
 
387
 
 
388
    bm->migration_compat_status =
 
389
        (bm->status & ~abused_bits) | (bm->bus->error_status & abused_bits);
 
390
}
 
391
 
 
392
/* This function accesses bm->bus->error_status which is loaded only after
 
393
 * BMDMA itself. This is why the function is called from ide_pci_post_load
 
394
 * instead of being registered with VMState where it would run too early. */
 
395
static int ide_bmdma_post_load(void *opaque, int version_id)
 
396
{
 
397
    BMDMAState *bm = opaque;
 
398
    uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS;
 
399
 
 
400
    if (bm->status == 0) {
 
401
        bm->status = bm->migration_compat_status & ~abused_bits;
 
402
        bm->bus->error_status |= bm->migration_compat_status & abused_bits;
 
403
    }
 
404
 
 
405
    return 0;
 
406
}
 
407
 
 
408
static const VMStateDescription vmstate_bmdma_current = {
 
409
    .name = "ide bmdma_current",
 
410
    .version_id = 1,
 
411
    .minimum_version_id = 1,
 
412
    .minimum_version_id_old = 1,
 
413
    .fields      = (VMStateField []) {
 
414
        VMSTATE_UINT32(cur_addr, BMDMAState),
 
415
        VMSTATE_UINT32(cur_prd_last, BMDMAState),
 
416
        VMSTATE_UINT32(cur_prd_addr, BMDMAState),
 
417
        VMSTATE_UINT32(cur_prd_len, BMDMAState),
 
418
        VMSTATE_END_OF_LIST()
 
419
    }
 
420
};
 
421
 
 
422
const VMStateDescription vmstate_bmdma_status = {
 
423
    .name ="ide bmdma/status",
 
424
    .version_id = 1,
 
425
    .minimum_version_id = 1,
 
426
    .minimum_version_id_old = 1,
 
427
    .fields = (VMStateField []) {
 
428
        VMSTATE_UINT8(status, BMDMAState),
 
429
        VMSTATE_END_OF_LIST()
 
430
    }
 
431
};
 
432
 
 
433
static const VMStateDescription vmstate_bmdma = {
 
434
    .name = "ide bmdma",
 
435
    .version_id = 3,
 
436
    .minimum_version_id = 0,
 
437
    .minimum_version_id_old = 0,
 
438
    .pre_save  = ide_bmdma_pre_save,
 
439
    .fields      = (VMStateField []) {
 
440
        VMSTATE_UINT8(cmd, BMDMAState),
 
441
        VMSTATE_UINT8(migration_compat_status, BMDMAState),
 
442
        VMSTATE_UINT32(addr, BMDMAState),
 
443
        VMSTATE_INT64(sector_num, BMDMAState),
 
444
        VMSTATE_UINT32(nsector, BMDMAState),
 
445
        VMSTATE_UINT8(unit, BMDMAState),
 
446
        VMSTATE_END_OF_LIST()
 
447
    },
 
448
    .subsections = (VMStateSubsection []) {
 
449
        {
 
450
            .vmsd = &vmstate_bmdma_current,
 
451
            .needed = ide_bmdma_current_needed,
 
452
        }, {
 
453
            .vmsd = &vmstate_bmdma_status,
 
454
            .needed = ide_bmdma_status_needed,
 
455
        }, {
 
456
            /* empty */
 
457
        }
 
458
    }
 
459
};
 
460
 
 
461
static int ide_pci_post_load(void *opaque, int version_id)
 
462
{
 
463
    PCIIDEState *d = opaque;
 
464
    int i;
 
465
 
 
466
    for(i = 0; i < 2; i++) {
 
467
        /* current versions always store 0/1, but older version
 
468
           stored bigger values. We only need last bit */
 
469
        d->bmdma[i].unit &= 1;
 
470
        ide_bmdma_post_load(&d->bmdma[i], -1);
 
471
    }
 
472
 
 
473
    return 0;
 
474
}
 
475
 
 
476
const VMStateDescription vmstate_ide_pci = {
 
477
    .name = "ide",
 
478
    .version_id = 3,
 
479
    .minimum_version_id = 0,
 
480
    .minimum_version_id_old = 0,
 
481
    .post_load = ide_pci_post_load,
 
482
    .fields      = (VMStateField []) {
 
483
        VMSTATE_PCI_DEVICE(dev, PCIIDEState),
 
484
        VMSTATE_STRUCT_ARRAY(bmdma, PCIIDEState, 2, 0,
 
485
                             vmstate_bmdma, BMDMAState),
 
486
        VMSTATE_IDE_BUS_ARRAY(bus, PCIIDEState, 2),
 
487
        VMSTATE_IDE_DRIVES(bus[0].ifs, PCIIDEState),
 
488
        VMSTATE_IDE_DRIVES(bus[1].ifs, PCIIDEState),
 
489
        VMSTATE_END_OF_LIST()
 
490
    }
 
491
};
 
492
 
 
493
void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table)
 
494
{
 
495
    PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
 
496
    static const int bus[4]  = { 0, 0, 1, 1 };
 
497
    static const int unit[4] = { 0, 1, 0, 1 };
 
498
    int i;
 
499
 
 
500
    for (i = 0; i < 4; i++) {
 
501
        if (hd_table[i] == NULL)
 
502
            continue;
 
503
        ide_create_drive(d->bus+bus[i], unit[i], hd_table[i]);
 
504
    }
 
505
}
 
506
 
 
507
static const struct IDEDMAOps bmdma_ops = {
 
508
    .start_dma = bmdma_start_dma,
 
509
    .start_transfer = bmdma_start_transfer,
 
510
    .prepare_buf = bmdma_prepare_buf,
 
511
    .rw_buf = bmdma_rw_buf,
 
512
    .set_unit = bmdma_set_unit,
 
513
    .add_status = bmdma_add_status,
 
514
    .set_inactive = bmdma_set_inactive,
 
515
    .restart_cb = bmdma_restart_cb,
 
516
    .reset = bmdma_reset,
 
517
};
 
518
 
 
519
void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d)
 
520
{
 
521
    qemu_irq *irq;
 
522
 
 
523
    if (bus->dma == &bm->dma) {
 
524
        return;
 
525
    }
 
526
 
 
527
    bm->dma.ops = &bmdma_ops;
 
528
    bus->dma = &bm->dma;
 
529
    bm->irq = bus->irq;
 
530
    irq = qemu_allocate_irqs(bmdma_irq, bm, 1);
 
531
    bus->irq = *irq;
 
532
    bm->pci_dev = d;
 
533
}