i8257.c 16.8 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU DMA emulation
B
bellard 已提交
3 4 5
 *
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
Peter Maydell 已提交
24
#include "qemu/osdep.h"
25
#include "hw/hw.h"
P
Paolo Bonzini 已提交
26
#include "hw/isa/isa.h"
27
#include "hw/isa/i8257.h"
28
#include "qemu/main-loop.h"
29
#include "trace.h"
B
bellard 已提交
30

H
Hervé Poussineau 已提交
31 32 33
#define I8257(obj) \
    OBJECT_CHECK(I8257State, (obj), TYPE_I8257)

B
bellard 已提交
34
/* #define DEBUG_DMA */
B
debug  
bellard 已提交
35

B
bellard 已提交
36
#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
B
bellard 已提交
37 38 39 40 41 42 43 44 45 46 47 48
#ifdef DEBUG_DMA
#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__)
#else
#define linfo(...)
#define ldebug(...)
#endif

#define ADDR 0
#define COUNT 1

enum {
B
bellard 已提交
49 50 51 52 53 54 55 56 57 58 59
    CMD_MEMORY_TO_MEMORY = 0x01,
    CMD_FIXED_ADDRESS    = 0x02,
    CMD_BLOCK_CONTROLLER = 0x04,
    CMD_COMPRESSED_TIME  = 0x08,
    CMD_CYCLIC_PRIORITY  = 0x10,
    CMD_EXTENDED_WRITE   = 0x20,
    CMD_LOW_DREQ         = 0x40,
    CMD_LOW_DACK         = 0x80,
    CMD_NOT_SUPPORTED    = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
    | CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
    | CMD_LOW_DREQ | CMD_LOW_DACK
B
bellard 已提交
60 61 62

};

63
static void i8257_dma_run(void *opaque);
A
aliguori 已提交
64

H
Hervé Poussineau 已提交
65
static const int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
66

67
static void i8257_write_page(void *opaque, uint32_t nport, uint32_t data)
B
bellard 已提交
68
{
69
    I8257State *d = opaque;
B
bellard 已提交
70 71
    int ichan;

72
    ichan = channels[nport & 7];
B
bellard 已提交
73
    if (-1 == ichan) {
B
bellard 已提交
74
        dolog ("invalid channel %#x %#x\n", nport, data);
B
bellard 已提交
75 76
        return;
    }
77 78 79
    d->regs[ichan].page = data;
}

80
static void i8257_write_pageh(void *opaque, uint32_t nport, uint32_t data)
81
{
82
    I8257State *d = opaque;
83
    int ichan;
B
bellard 已提交
84

85
    ichan = channels[nport & 7];
86
    if (-1 == ichan) {
B
bellard 已提交
87
        dolog ("invalid channel %#x %#x\n", nport, data);
88 89 90 91
        return;
    }
    d->regs[ichan].pageh = data;
}
92

93
static uint32_t i8257_read_page(void *opaque, uint32_t nport)
94
{
95
    I8257State *d = opaque;
96 97 98
    int ichan;

    ichan = channels[nport & 7];
99
    if (-1 == ichan) {
B
bellard 已提交
100
        dolog ("invalid channel read %#x\n", nport);
101 102 103
        return 0;
    }
    return d->regs[ichan].page;
B
bellard 已提交
104 105
}

106
static uint32_t i8257_read_pageh(void *opaque, uint32_t nport)
107
{
108
    I8257State *d = opaque;
109 110 111 112
    int ichan;

    ichan = channels[nport & 7];
    if (-1 == ichan) {
B
bellard 已提交
113
        dolog ("invalid channel read %#x\n", nport);
114 115 116 117 118
        return 0;
    }
    return d->regs[ichan].pageh;
}

119
static inline void i8257_init_chan(I8257State *d, int ichan)
B
bellard 已提交
120
{
121
    I8257Regs *r;
B
bellard 已提交
122

123
    r = d->regs + ichan;
B
bellard 已提交
124
    r->now[ADDR] = r->base[ADDR] << d->dshift;
B
bellard 已提交
125 126 127
    r->now[COUNT] = 0;
}

128
static inline int i8257_getff(I8257State *d)
B
bellard 已提交
129 130 131
{
    int ff;

132 133
    ff = d->flip_flop;
    d->flip_flop = !ff;
B
bellard 已提交
134 135 136
    return ff;
}

137
static uint64_t i8257_read_chan(void *opaque, hwaddr nport, unsigned size)
B
bellard 已提交
138
{
139
    I8257State *d = opaque;
B
bellard 已提交
140
    int ichan, nreg, iport, ff, val, dir;
141
    I8257Regs *r;
B
bellard 已提交
142

143 144 145 146
    iport = (nport >> d->dshift) & 0x0f;
    ichan = iport >> 1;
    nreg = iport & 1;
    r = d->regs + ichan;
B
bellard 已提交
147

B
bellard 已提交
148
    dir = ((r->mode >> 5) & 1) ? -1 : 1;
149
    ff = i8257_getff(d);
B
bellard 已提交
150
    if (nreg)
151
        val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
B
bellard 已提交
152
    else
B
bellard 已提交
153
        val = r->now[ADDR] + r->now[COUNT] * dir;
B
bellard 已提交
154

B
bellard 已提交
155
    ldebug ("read_chan %#x -> %d\n", iport, val);
156
    return (val >> (d->dshift + (ff << 3))) & 0xff;
B
bellard 已提交
157 158
}

159 160
static void i8257_write_chan(void *opaque, hwaddr nport, uint64_t data,
                             unsigned int size)
B
bellard 已提交
161
{
162
    I8257State *d = opaque;
163
    int iport, ichan, nreg;
164
    I8257Regs *r;
B
bellard 已提交
165

166 167 168 169
    iport = (nport >> d->dshift) & 0x0f;
    ichan = iport >> 1;
    nreg = iport & 1;
    r = d->regs + ichan;
170
    if (i8257_getff(d)) {
B
bellard 已提交
171
        r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
172
        i8257_init_chan(d, ichan);
B
bellard 已提交
173 174
    } else {
        r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
B
bellard 已提交
175 176 177
    }
}

178 179
static void i8257_write_cont(void *opaque, hwaddr nport, uint64_t data,
                             unsigned int size)
B
bellard 已提交
180
{
181
    I8257State *d = opaque;
B
bellard 已提交
182
    int iport, ichan = 0;
B
bellard 已提交
183

184
    iport = (nport >> d->dshift) & 0x0f;
B
bellard 已提交
185
    switch (iport) {
186
    case 0x00:                  /* command */
B
bellard 已提交
187
        if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
J
Julien Grall 已提交
188
            dolog("command %"PRIx64" not supported\n", data);
B
bellard 已提交
189
            return;
B
bellard 已提交
190 191 192 193
        }
        d->command = data;
        break;

194
    case 0x01:
B
bellard 已提交
195 196 197 198 199 200 201 202
        ichan = data & 3;
        if (data & 4) {
            d->status |= 1 << (ichan + 4);
        }
        else {
            d->status &= ~(1 << (ichan + 4));
        }
        d->status &= ~(1 << ichan);
203
        i8257_dma_run(d);
B
bellard 已提交
204 205
        break;

206
    case 0x02:                  /* single mask */
B
bellard 已提交
207 208 209 210
        if (data & 4)
            d->mask |= 1 << (data & 3);
        else
            d->mask &= ~(1 << (data & 3));
211
        i8257_dma_run(d);
B
bellard 已提交
212 213
        break;

214
    case 0x03:                  /* mode */
B
bellard 已提交
215
        {
B
bellard 已提交
216 217
            ichan = data & 3;
#ifdef DEBUG_DMA
B
bellard 已提交
218 219
            {
                int op, ai, dir, opmode;
B
bellard 已提交
220 221 222 223
                op = (data >> 2) & 3;
                ai = (data >> 4) & 1;
                dir = (data >> 5) & 1;
                opmode = (data >> 6) & 3;
B
bellard 已提交
224

B
bellard 已提交
225 226
                linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
                       ichan, op, ai, dir, opmode);
B
bellard 已提交
227
            }
B
bellard 已提交
228 229 230 231 232
#endif
            d->regs[ichan].mode = data;
            break;
        }

233
    case 0x04:                  /* clear flip flop */
B
bellard 已提交
234 235 236
        d->flip_flop = 0;
        break;

237
    case 0x05:                  /* reset */
B
bellard 已提交
238 239 240 241 242 243
        d->flip_flop = 0;
        d->mask = ~0;
        d->status = 0;
        d->command = 0;
        break;

244
    case 0x06:                  /* clear mask for all channels */
B
bellard 已提交
245
        d->mask = 0;
246
        i8257_dma_run(d);
B
bellard 已提交
247 248
        break;

249
    case 0x07:                  /* write mask for all channels */
B
bellard 已提交
250
        d->mask = data;
251
        i8257_dma_run(d);
B
bellard 已提交
252 253 254
        break;

    default:
B
bellard 已提交
255
        dolog ("unknown iport %#x\n", iport);
B
bellard 已提交
256
        break;
B
bellard 已提交
257 258
    }

B
bellard 已提交
259
#ifdef DEBUG_DMA
B
bellard 已提交
260
    if (0xc != iport) {
B
bellard 已提交
261
        linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n",
262
               nport, ichan, data);
B
bellard 已提交
263 264 265 266
    }
#endif
}

267
static uint64_t i8257_read_cont(void *opaque, hwaddr nport, unsigned size)
268
{
269
    I8257State *d = opaque;
270
    int iport, val;
B
bellard 已提交
271

272 273
    iport = (nport >> d->dshift) & 0x0f;
    switch (iport) {
274
    case 0x00:                  /* status */
275 276 277
        val = d->status;
        d->status &= 0xf0;
        break;
278
    case 0x01:                  /* mask */
279 280 281 282 283 284
        val = d->mask;
        break;
    default:
        val = 0;
        break;
    }
B
bellard 已提交
285 286

    ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val);
287 288 289
    return val;
}

290 291 292 293 294 295 296
static IsaDmaTransferMode i8257_dma_get_transfer_mode(IsaDma *obj, int nchan)
{
    I8257State *d = I8257(obj);
    return (d->regs[nchan & 3].mode >> 2) & 3;
}

static bool i8257_dma_has_autoinitialization(IsaDma *obj, int nchan)
B
bellard 已提交
297
{
298 299
    I8257State *d = I8257(obj);
    return (d->regs[nchan & 3].mode >> 4) & 1;
B
bellard 已提交
300 301
}

302
static void i8257_dma_hold_DREQ(IsaDma *obj, int nchan)
B
bellard 已提交
303
{
304 305
    I8257State *d = I8257(obj);
    int ichan;
B
bellard 已提交
306 307

    ichan = nchan & 3;
308 309
    d->status |= 1 << (ichan + 4);
    i8257_dma_run(d);
B
bellard 已提交
310 311
}

312
static void i8257_dma_release_DREQ(IsaDma *obj, int nchan)
B
bellard 已提交
313
{
314 315
    I8257State *d = I8257(obj);
    int ichan;
B
bellard 已提交
316 317

    ichan = nchan & 3;
318 319
    d->status &= ~(1 << (ichan + 4));
    i8257_dma_run(d);
B
bellard 已提交
320 321
}

322
static void i8257_channel_run(I8257State *d, int ichan)
B
bellard 已提交
323
{
324
    int ncont = d->dshift;
B
bellard 已提交
325
    int n;
326
    I8257Regs *r = &d->regs[ichan];
B
bellard 已提交
327 328
#ifdef DEBUG_DMA
    int dir, opmode;
B
bellard 已提交
329

B
bellard 已提交
330 331
    dir = (r->mode >> 5) & 1;
    opmode = (r->mode >> 6) & 3;
B
bellard 已提交
332

B
bellard 已提交
333 334 335 336 337 338 339
    if (dir) {
        dolog ("DMA in address decrement mode\n");
    }
    if (opmode != 1) {
        dolog ("DMA not in single mode select %#x\n", opmode);
    }
#endif
B
bellard 已提交
340

B
bellard 已提交
341 342 343 344
    n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
                             r->now[COUNT], (r->base[COUNT] + 1) << ncont);
    r->now[COUNT] = n;
    ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
345 346 347 348
    if (n == (r->base[COUNT] + 1) << ncont) {
        ldebug("transfer done\n");
        d->status |= (1 << ichan);
    }
B
bellard 已提交
349 350
}

351
static void i8257_dma_run(void *opaque)
B
bellard 已提交
352
{
353 354
    I8257State *d = opaque;
    int ichan;
A
aliguori 已提交
355
    int rearm = 0;
356

357
    if (d->running) {
358 359 360
        rearm = 1;
        goto out;
    } else {
361
        d->running = 1;
362
    }
B
bellard 已提交
363

364 365
    for (ichan = 0; ichan < 4; ichan++) {
        int mask;
B
bellard 已提交
366

367
        mask = 1 << ichan;
B
bellard 已提交
368

369 370 371
        if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
            i8257_channel_run(d, ichan);
            rearm = 1;
B
bellard 已提交
372 373
        }
    }
A
aliguori 已提交
374

375
    d->running = 0;
376
out:
377
    if (rearm) {
378 379
        qemu_bh_schedule_idle(d->dma_bh);
        d->dma_bh_scheduled = true;
380
    }
A
aliguori 已提交
381 382
}

383
static void i8257_dma_register_channel(IsaDma *obj, int nchan,
384
                                       IsaDmaTransferHandler transfer_handler,
385
                                       void *opaque)
B
bellard 已提交
386
{
387
    I8257State *d = I8257(obj);
388
    I8257Regs *r;
389
    int ichan;
B
bellard 已提交
390 391 392

    ichan = nchan & 3;

393
    r = d->regs + ichan;
B
bellard 已提交
394 395 396 397
    r->transfer_handler = transfer_handler;
    r->opaque = opaque;
}

398 399
static int i8257_dma_read_memory(IsaDma *obj, int nchan, void *buf, int pos,
                                 int len)
B
bellard 已提交
400
{
401 402
    I8257State *d = I8257(obj);
    I8257Regs *r = &d->regs[nchan & 3];
A
Avi Kivity 已提交
403
    hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
B
bellard 已提交
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421

    if (r->mode & 0x20) {
        int i;
        uint8_t *p = buf;

        cpu_physical_memory_read (addr - pos - len, buf, len);
        /* What about 16bit transfers? */
        for (i = 0; i < len >> 1; i++) {
            uint8_t b = p[len - i - 1];
            p[i] = b;
        }
    }
    else
        cpu_physical_memory_read (addr + pos, buf, len);

    return len;
}

422 423
static int i8257_dma_write_memory(IsaDma *obj, int nchan, void *buf, int pos,
                                 int len)
B
bellard 已提交
424
{
425 426
    I8257State *s = I8257(obj);
    I8257Regs *r = &s->regs[nchan & 3];
A
Avi Kivity 已提交
427
    hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
B
bellard 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445

    if (r->mode & 0x20) {
        int i;
        uint8_t *p = buf;

        cpu_physical_memory_write (addr - pos - len, buf, len);
        /* What about 16bit transfers? */
        for (i = 0; i < len; i++) {
            uint8_t b = p[len - i - 1];
            p[i] = b;
        }
    }
    else
        cpu_physical_memory_write (addr + pos, buf, len);

    return len;
}

446 447 448
/* request the emulator to transfer a new DMA memory block ASAP (even
 * if the idle bottom half would not have exited the iothread yet).
 */
449
static void i8257_dma_schedule(IsaDma *obj)
B
bellard 已提交
450
{
451 452
    I8257State *d = I8257(obj);
    if (d->dma_bh_scheduled) {
453 454
        qemu_notify_event();
    }
B
bellard 已提交
455 456
}

H
Hervé Poussineau 已提交
457
static void i8257_reset(DeviceState *dev)
B
bellard 已提交
458
{
H
Hervé Poussineau 已提交
459
    I8257State *d = I8257(dev);
460
    i8257_write_cont(d, (0x05 << d->dshift), 0, 1);
B
bellard 已提交
461 462
}

463 464
static int i8257_phony_handler(void *opaque, int nchan, int dma_pos,
                               int dma_len)
465
{
466
    trace_i8257_unregistered_dma(nchan, dma_pos, dma_len);
467 468 469
    return dma_pos;
}

J
Julien Grall 已提交
470 471

static const MemoryRegionOps channel_io_ops = {
472 473
    .read = i8257_read_chan,
    .write = i8257_write_chan,
J
Julien Grall 已提交
474 475 476 477 478 479 480 481 482
    .endianness = DEVICE_NATIVE_ENDIAN,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
};

/* IOport from page_base */
static const MemoryRegionPortio page_portio_list[] = {
483 484
    { 0x01, 3, 1, .write = i8257_write_page, .read = i8257_read_page, },
    { 0x07, 1, 1, .write = i8257_write_page, .read = i8257_read_page, },
J
Julien Grall 已提交
485 486 487 488 489
    PORTIO_END_OF_LIST(),
};

/* IOport from pageh_base */
static const MemoryRegionPortio pageh_portio_list[] = {
490 491
    { 0x01, 3, 1, .write = i8257_write_pageh, .read = i8257_read_pageh, },
    { 0x07, 3, 1, .write = i8257_write_pageh, .read = i8257_read_pageh, },
J
Julien Grall 已提交
492 493 494 495
    PORTIO_END_OF_LIST(),
};

static const MemoryRegionOps cont_io_ops = {
496 497
    .read = i8257_read_cont,
    .write = i8257_write_cont,
J
Julien Grall 已提交
498 499 500 501 502 503 504
    .endianness = DEVICE_NATIVE_ENDIAN,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
};

505
static const VMStateDescription vmstate_i8257_regs = {
J
Juan Quintela 已提交
506 507 508
    .name = "dma_regs",
    .version_id = 1,
    .minimum_version_id = 1,
509
    .fields = (VMStateField[]) {
510 511 512 513 514 515 516
        VMSTATE_INT32_ARRAY(now, I8257Regs, 2),
        VMSTATE_UINT16_ARRAY(base, I8257Regs, 2),
        VMSTATE_UINT8(mode, I8257Regs),
        VMSTATE_UINT8(page, I8257Regs),
        VMSTATE_UINT8(pageh, I8257Regs),
        VMSTATE_UINT8(dack, I8257Regs),
        VMSTATE_UINT8(eop, I8257Regs),
J
Juan Quintela 已提交
517
        VMSTATE_END_OF_LIST()
B
bellard 已提交
518
    }
J
Juan Quintela 已提交
519
};
B
bellard 已提交
520

521
static int i8257_post_load(void *opaque, int version_id)
B
bellard 已提交
522
{
523 524
    I8257State *d = opaque;
    i8257_dma_run(d);
A
aliguori 已提交
525

B
bellard 已提交
526 527 528
    return 0;
}

H
Hervé Poussineau 已提交
529
static const VMStateDescription vmstate_i8257 = {
J
Juan Quintela 已提交
530 531 532
    .name = "dma",
    .version_id = 1,
    .minimum_version_id = 1,
533
    .post_load = i8257_post_load,
534
    .fields = (VMStateField[]) {
535 536 537 538
        VMSTATE_UINT8(command, I8257State),
        VMSTATE_UINT8(mask, I8257State),
        VMSTATE_UINT8(flip_flop, I8257State),
        VMSTATE_INT32(dshift, I8257State),
539 540
        VMSTATE_STRUCT_ARRAY(regs, I8257State, 4, 1, vmstate_i8257_regs,
                             I8257Regs),
J
Juan Quintela 已提交
541 542 543 544
        VMSTATE_END_OF_LIST()
    }
};

H
Hervé Poussineau 已提交
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
static void i8257_realize(DeviceState *dev, Error **errp)
{
    ISADevice *isa = ISA_DEVICE(dev);
    I8257State *d = I8257(dev);
    int i;

    memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d,
                          "dma-chan", 8 << d->dshift);
    memory_region_add_subregion(isa_address_space_io(isa),
                                d->base, &d->channel_io);

    isa_register_portio_list(isa, d->page_base, page_portio_list, d,
                             "dma-page");
    if (d->pageh_base >= 0) {
        isa_register_portio_list(isa, d->pageh_base, pageh_portio_list, d,
                                 "dma-pageh");
    }

    memory_region_init_io(&d->cont_io, OBJECT(isa), &cont_io_ops, d,
                          "dma-cont", 8 << d->dshift);
    memory_region_add_subregion(isa_address_space_io(isa),
                                d->base + (8 << d->dshift), &d->cont_io);

    for (i = 0; i < ARRAY_SIZE(d->regs); ++i) {
        d->regs[i].transfer_handler = i8257_phony_handler;
    }

    d->dma_bh = qemu_bh_new(i8257_dma_run, d);
}

static Property i8257_properties[] = {
    DEFINE_PROP_INT32("base", I8257State, base, 0x00),
    DEFINE_PROP_INT32("page-base", I8257State, page_base, 0x80),
    DEFINE_PROP_INT32("pageh-base", I8257State, pageh_base, 0x480),
    DEFINE_PROP_INT32("dshift", I8257State, dshift, 0),
    DEFINE_PROP_END_OF_LIST()
};

static void i8257_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
586
    IsaDmaClass *idc = ISADMA_CLASS(klass);
H
Hervé Poussineau 已提交
587 588 589 590 591

    dc->realize = i8257_realize;
    dc->reset = i8257_reset;
    dc->vmsd = &vmstate_i8257;
    dc->props = i8257_properties;
592 593 594 595 596 597 598 599 600 601 602

    idc->get_transfer_mode = i8257_dma_get_transfer_mode;
    idc->has_autoinitialization = i8257_dma_has_autoinitialization;
    idc->read_memory = i8257_dma_read_memory;
    idc->write_memory = i8257_dma_write_memory;
    idc->hold_DREQ = i8257_dma_hold_DREQ;
    idc->release_DREQ = i8257_dma_release_DREQ;
    idc->schedule = i8257_dma_schedule;
    idc->register_channel = i8257_dma_register_channel;
}

H
Hervé Poussineau 已提交
603 604 605 606 607
static const TypeInfo i8257_info = {
    .name = TYPE_I8257,
    .parent = TYPE_ISA_DEVICE,
    .instance_size = sizeof(I8257State),
    .class_init = i8257_class_init,
608 609 610 611
    .interfaces = (InterfaceInfo[]) {
        { TYPE_ISADMA },
        { }
    }
H
Hervé Poussineau 已提交
612 613 614 615 616 617 618 619 620
};

static void i8257_register_types(void)
{
    type_register_static(&i8257_info);
}

type_init(i8257_register_types)

621
void DMA_init(ISABus *bus, int high_page_enable)
622
{
H
Hervé Poussineau 已提交
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
    ISADevice *isa1, *isa2;
    DeviceState *d;

    isa1 = isa_create(bus, TYPE_I8257);
    d = DEVICE(isa1);
    qdev_prop_set_int32(d, "base", 0x00);
    qdev_prop_set_int32(d, "page-base", 0x80);
    qdev_prop_set_int32(d, "pageh-base", high_page_enable ? 0x480 : -1);
    qdev_prop_set_int32(d, "dshift", 0);
    qdev_init_nofail(d);

    isa2 = isa_create(bus, TYPE_I8257);
    d = DEVICE(isa2);
    qdev_prop_set_int32(d, "base", 0xc0);
    qdev_prop_set_int32(d, "page-base", 0x88);
    qdev_prop_set_int32(d, "pageh-base", high_page_enable ? 0x488 : -1);
    qdev_prop_set_int32(d, "dshift", 1);
    qdev_init_nofail(d);
641 642

    isa_bus_dma(bus, ISADMA(isa1), ISADMA(isa2));
B
bellard 已提交
643
}