parallel.c 17.9 KB
Newer Older
1 2
/*
 * QEMU Parallel PORT emulation
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003-2005 Fabrice Bellard
5
 * Copyright (c) 2007 Marko Kohtala
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 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.
 */
25
#include "hw/hw.h"
26
#include "char/char.h"
P
Paolo Bonzini 已提交
27 28
#include "hw/isa/isa.h"
#include "hw/i386/pc.h"
29
#include "sysemu/sysemu.h"
30 31 32

//#define DEBUG_PARALLEL

33
#ifdef DEBUG_PARALLEL
34
#define pdebug(fmt, ...) printf("pp: " fmt, ## __VA_ARGS__)
35
#else
36
#define pdebug(fmt, ...) ((void)0)
37 38 39 40 41 42 43 44
#endif

#define PARA_REG_DATA 0
#define PARA_REG_STS 1
#define PARA_REG_CTR 2
#define PARA_REG_EPP_ADDR 3
#define PARA_REG_EPP_DATA 4

45 46 47 48 49 50 51 52
/*
 * These are the definitions for the Printer Status Register
 */
#define PARA_STS_BUSY	0x80	/* Busy complement */
#define PARA_STS_ACK	0x40	/* Acknowledge */
#define PARA_STS_PAPER	0x20	/* Out of paper */
#define PARA_STS_ONLINE	0x10	/* Online */
#define PARA_STS_ERROR	0x08	/* Error complement */
53
#define PARA_STS_TMOUT	0x01	/* EPP timeout */
54 55 56 57

/*
 * These are the definitions for the Printer Control Register
 */
58
#define PARA_CTR_DIR	0x20	/* Direction (1=read, 0=write) */
59 60 61 62 63 64
#define PARA_CTR_INTEN	0x10	/* IRQ Enable */
#define PARA_CTR_SELECT	0x08	/* Select In complement */
#define PARA_CTR_INIT	0x04	/* Initialize Printer complement */
#define PARA_CTR_AUTOLF	0x02	/* Auto linefeed complement */
#define PARA_CTR_STROBE	0x01	/* Strobe complement */

65 66
#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)

B
Blue Swirl 已提交
67
typedef struct ParallelState {
A
Avi Kivity 已提交
68
    MemoryRegion iomem;
69 70 71
    uint8_t dataw;
    uint8_t datar;
    uint8_t status;
72
    uint8_t control;
P
pbrook 已提交
73
    qemu_irq irq;
74 75
    int irq_pending;
    CharDriverState *chr;
B
bellard 已提交
76
    int hw_driver;
77 78
    int epp_timeout;
    uint32_t last_read_offset; /* For debugging */
79 80
    /* Memory-mapped interface */
    int it_shift;
B
Blue Swirl 已提交
81
} ParallelState;
82

G
Gerd Hoffmann 已提交
83 84
typedef struct ISAParallelState {
    ISADevice dev;
85
    uint32_t index;
G
Gerd Hoffmann 已提交
86 87 88 89 90
    uint32_t iobase;
    uint32_t isairq;
    ParallelState state;
} ISAParallelState;

91 92 93
static void parallel_update_irq(ParallelState *s)
{
    if (s->irq_pending)
P
pbrook 已提交
94
        qemu_irq_raise(s->irq);
95
    else
P
pbrook 已提交
96
        qemu_irq_lower(s->irq);
97 98
}

99 100
static void
parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
101 102
{
    ParallelState *s = opaque;
103

104 105 106 107 108
    pdebug("write addr=0x%02x val=0x%02x\n", addr, val);

    addr &= 7;
    switch(addr) {
    case PARA_REG_DATA:
T
ths 已提交
109 110
        s->dataw = val;
        parallel_update_irq(s);
111 112
        break;
    case PARA_REG_CTR:
113
        val |= 0xc0;
T
ths 已提交
114 115 116 117 118 119 120 121 122 123
        if ((val & PARA_CTR_INIT) == 0 ) {
            s->status = PARA_STS_BUSY;
            s->status |= PARA_STS_ACK;
            s->status |= PARA_STS_ONLINE;
            s->status |= PARA_STS_ERROR;
        }
        else if (val & PARA_CTR_SELECT) {
            if (val & PARA_CTR_STROBE) {
                s->status &= ~PARA_STS_BUSY;
                if ((s->control & PARA_CTR_STROBE) == 0)
124
                    qemu_chr_fe_write(s->chr, &s->dataw, 1);
T
ths 已提交
125 126 127 128 129 130 131 132
            } else {
                if (s->control & PARA_CTR_INTEN) {
                    s->irq_pending = 1;
                }
            }
        }
        parallel_update_irq(s);
        s->control = val;
133 134 135 136 137 138 139 140
        break;
    }
}

static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
{
    ParallelState *s = opaque;
    uint8_t parm = val;
A
aurel32 已提交
141
    int dir;
142 143 144 145 146 147

    /* Sometimes programs do several writes for timing purposes on old
       HW. Take care not to waste time on writes that do nothing. */

    s->last_read_offset = ~0U;

148 149
    addr &= 7;
    switch(addr) {
150 151
    case PARA_REG_DATA:
        if (s->dataw == val)
T
ths 已提交
152 153
            return;
        pdebug("wd%02x\n", val);
154
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
T
ths 已提交
155
        s->dataw = val;
156
        break;
157
    case PARA_REG_STS:
T
ths 已提交
158 159 160 161
        pdebug("ws%02x\n", val);
        if (val & PARA_STS_TMOUT)
            s->epp_timeout = 0;
        break;
162 163 164
    case PARA_REG_CTR:
        val |= 0xc0;
        if (s->control == val)
T
ths 已提交
165 166
            return;
        pdebug("wc%02x\n", val);
A
aurel32 已提交
167 168 169 170 171 172 173

        if ((val & PARA_CTR_DIR) != (s->control & PARA_CTR_DIR)) {
            if (val & PARA_CTR_DIR) {
                dir = 1;
            } else {
                dir = 0;
            }
174
            qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_DATA_DIR, &dir);
A
aurel32 已提交
175 176 177
            parm &= ~PARA_CTR_DIR;
        }

178
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
T
ths 已提交
179
        s->control = val;
180
        break;
181
    case PARA_REG_EPP_ADDR:
T
ths 已提交
182 183 184 185 186
        if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
            /* Controls not correct for EPP address cycle, so do nothing */
            pdebug("wa%02x s\n", val);
        else {
            struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
187
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
T
ths 已提交
188 189 190 191 192 193 194
                s->epp_timeout = 1;
                pdebug("wa%02x t\n", val);
            }
            else
                pdebug("wa%02x\n", val);
        }
        break;
195
    case PARA_REG_EPP_DATA:
T
ths 已提交
196 197 198 199 200
        if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
            /* Controls not correct for EPP data cycle, so do nothing */
            pdebug("we%02x s\n", val);
        else {
            struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
201
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
T
ths 已提交
202 203 204 205 206 207 208
                s->epp_timeout = 1;
                pdebug("we%02x t\n", val);
            }
            else
                pdebug("we%02x\n", val);
        }
        break;
209 210 211 212 213 214 215 216 217 218
    }
}

static void
parallel_ioport_eppdata_write_hw2(void *opaque, uint32_t addr, uint32_t val)
{
    ParallelState *s = opaque;
    uint16_t eppdata = cpu_to_le16(val);
    int err;
    struct ParallelIOArg ioarg = {
T
ths 已提交
219
        .buffer = &eppdata, .count = sizeof(eppdata)
220 221
    };
    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
T
ths 已提交
222 223 224
        /* Controls not correct for EPP data cycle, so do nothing */
        pdebug("we%04x s\n", val);
        return;
225
    }
226
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
227
    if (err) {
T
ths 已提交
228 229
        s->epp_timeout = 1;
        pdebug("we%04x t\n", val);
230 231
    }
    else
T
ths 已提交
232
        pdebug("we%04x\n", val);
233 234 235 236 237 238 239 240 241
}

static void
parallel_ioport_eppdata_write_hw4(void *opaque, uint32_t addr, uint32_t val)
{
    ParallelState *s = opaque;
    uint32_t eppdata = cpu_to_le32(val);
    int err;
    struct ParallelIOArg ioarg = {
T
ths 已提交
242
        .buffer = &eppdata, .count = sizeof(eppdata)
243 244
    };
    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
T
ths 已提交
245 246 247
        /* Controls not correct for EPP data cycle, so do nothing */
        pdebug("we%08x s\n", val);
        return;
248
    }
249
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
250
    if (err) {
T
ths 已提交
251 252
        s->epp_timeout = 1;
        pdebug("we%08x t\n", val);
253
    }
254
    else
T
ths 已提交
255
        pdebug("we%08x\n", val);
256 257
}

258
static uint32_t parallel_ioport_read_sw(void *opaque, uint32_t addr)
259 260 261 262 263 264
{
    ParallelState *s = opaque;
    uint32_t ret = 0xff;

    addr &= 7;
    switch(addr) {
265
    case PARA_REG_DATA:
T
ths 已提交
266 267 268 269
        if (s->control & PARA_CTR_DIR)
            ret = s->datar;
        else
            ret = s->dataw;
270
        break;
271
    case PARA_REG_STS:
T
ths 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284
        ret = s->status;
        s->irq_pending = 0;
        if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
            /* XXX Fixme: wait 5 microseconds */
            if (s->status & PARA_STS_ACK)
                s->status &= ~PARA_STS_ACK;
            else {
                /* XXX Fixme: wait 5 microseconds */
                s->status |= PARA_STS_ACK;
                s->status |= PARA_STS_BUSY;
            }
        }
        parallel_update_irq(s);
285
        break;
286
    case PARA_REG_CTR:
287 288 289
        ret = s->control;
        break;
    }
290 291 292 293 294 295 296 297 298 299 300
    pdebug("read addr=0x%02x val=0x%02x\n", addr, ret);
    return ret;
}

static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
{
    ParallelState *s = opaque;
    uint8_t ret = 0xff;
    addr &= 7;
    switch(addr) {
    case PARA_REG_DATA:
301
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
T
ths 已提交
302 303
        if (s->last_read_offset != addr || s->datar != ret)
            pdebug("rd%02x\n", ret);
304 305 306
        s->datar = ret;
        break;
    case PARA_REG_STS:
307
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
T
ths 已提交
308 309 310 311 312 313
        ret &= ~PARA_STS_TMOUT;
        if (s->epp_timeout)
            ret |= PARA_STS_TMOUT;
        if (s->last_read_offset != addr || s->status != ret)
            pdebug("rs%02x\n", ret);
        s->status = ret;
314 315 316
        break;
    case PARA_REG_CTR:
        /* s->control has some bits fixed to 1. It is zero only when
T
ths 已提交
317 318
           it has not been yet written to.  */
        if (s->control == 0) {
319
            qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
T
ths 已提交
320 321 322 323 324 325 326 327 328
            if (s->last_read_offset != addr)
                pdebug("rc%02x\n", ret);
            s->control = ret;
        }
        else {
            ret = s->control;
            if (s->last_read_offset != addr)
                pdebug("rc%02x\n", ret);
        }
329 330
        break;
    case PARA_REG_EPP_ADDR:
T
ths 已提交
331 332 333 334 335
        if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
            /* Controls not correct for EPP addr cycle, so do nothing */
            pdebug("ra%02x s\n", ret);
        else {
            struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
336
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
T
ths 已提交
337 338 339 340 341 342 343
                s->epp_timeout = 1;
                pdebug("ra%02x t\n", ret);
            }
            else
                pdebug("ra%02x\n", ret);
        }
        break;
344
    case PARA_REG_EPP_DATA:
T
ths 已提交
345 346 347 348 349
        if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
            /* Controls not correct for EPP data cycle, so do nothing */
            pdebug("re%02x s\n", ret);
        else {
            struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
350
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
T
ths 已提交
351 352 353 354 355 356 357
                s->epp_timeout = 1;
                pdebug("re%02x t\n", ret);
            }
            else
                pdebug("re%02x\n", ret);
        }
        break;
358 359 360 361 362 363 364 365 366 367 368 369 370
    }
    s->last_read_offset = addr;
    return ret;
}

static uint32_t
parallel_ioport_eppdata_read_hw2(void *opaque, uint32_t addr)
{
    ParallelState *s = opaque;
    uint32_t ret;
    uint16_t eppdata = ~0;
    int err;
    struct ParallelIOArg ioarg = {
T
ths 已提交
371
        .buffer = &eppdata, .count = sizeof(eppdata)
372 373
    };
    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
T
ths 已提交
374 375 376
        /* Controls not correct for EPP data cycle, so do nothing */
        pdebug("re%04x s\n", eppdata);
        return eppdata;
377
    }
378
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
379 380 381
    ret = le16_to_cpu(eppdata);

    if (err) {
T
ths 已提交
382 383
        s->epp_timeout = 1;
        pdebug("re%04x t\n", ret);
384 385
    }
    else
T
ths 已提交
386
        pdebug("re%04x\n", ret);
387 388 389 390 391 392 393 394 395 396 397
    return ret;
}

static uint32_t
parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
{
    ParallelState *s = opaque;
    uint32_t ret;
    uint32_t eppdata = ~0U;
    int err;
    struct ParallelIOArg ioarg = {
T
ths 已提交
398
        .buffer = &eppdata, .count = sizeof(eppdata)
399 400
    };
    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
T
ths 已提交
401 402 403
        /* Controls not correct for EPP data cycle, so do nothing */
        pdebug("re%08x s\n", eppdata);
        return eppdata;
404
    }
405
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
406 407 408
    ret = le32_to_cpu(eppdata);

    if (err) {
T
ths 已提交
409 410
        s->epp_timeout = 1;
        pdebug("re%08x t\n", ret);
411 412
    }
    else
T
ths 已提交
413
        pdebug("re%08x\n", ret);
414 415 416 417 418
    return ret;
}

static void parallel_ioport_ecp_write(void *opaque, uint32_t addr, uint32_t val)
{
419
    pdebug("wecp%d=%02x\n", addr & 7, val);
420 421 422 423 424
}

static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr)
{
    uint8_t ret = 0xff;
425 426

    pdebug("recp%d:%02x\n", addr & 7, ret);
427 428 429
    return ret;
}

A
aurel32 已提交
430
static void parallel_reset(void *opaque)
431
{
A
aurel32 已提交
432 433
    ParallelState *s = opaque;

434 435
    s->datar = ~0;
    s->dataw = ~0;
436 437 438 439
    s->status = PARA_STS_BUSY;
    s->status |= PARA_STS_ACK;
    s->status |= PARA_STS_ONLINE;
    s->status |= PARA_STS_ERROR;
440
    s->status |= PARA_STS_TMOUT;
441 442
    s->control = PARA_CTR_SELECT;
    s->control |= PARA_CTR_INIT;
443
    s->control |= 0xc0;
444 445 446 447
    s->irq_pending = 0;
    s->hw_driver = 0;
    s->epp_timeout = 0;
    s->last_read_offset = ~0U;
448 449
}

450 451
static const int isa_parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
static const MemoryRegionPortio isa_parallel_portio_hw_list[] = {
    { 0, 8, 1,
      .read = parallel_ioport_read_hw,
      .write = parallel_ioport_write_hw },
    { 4, 1, 2,
      .read = parallel_ioport_eppdata_read_hw2,
      .write = parallel_ioport_eppdata_write_hw2 },
    { 4, 1, 4,
      .read = parallel_ioport_eppdata_read_hw4,
      .write = parallel_ioport_eppdata_write_hw4 },
    { 0x400, 8, 1,
      .read = parallel_ioport_ecp_read,
      .write = parallel_ioport_ecp_write },
    PORTIO_END_OF_LIST(),
};

static const MemoryRegionPortio isa_parallel_portio_sw_list[] = {
    { 0, 8, 1,
      .read = parallel_ioport_read_sw,
      .write = parallel_ioport_write_sw },
    PORTIO_END_OF_LIST(),
};

G
Gerd Hoffmann 已提交
475
static int parallel_isa_initfn(ISADevice *dev)
476
{
477
    static int index;
G
Gerd Hoffmann 已提交
478 479
    ISAParallelState *isa = DO_UPCAST(ISAParallelState, dev, dev);
    ParallelState *s = &isa->state;
480
    int base;
481 482
    uint8_t dummy;

G
Gerd Hoffmann 已提交
483 484 485 486 487
    if (!s->chr) {
        fprintf(stderr, "Can't create parallel device, empty char device\n");
        exit(1);
    }

488 489 490 491 492 493 494 495 496
    if (isa->index == -1)
        isa->index = index;
    if (isa->index >= MAX_PARALLEL_PORTS)
        return -1;
    if (isa->iobase == -1)
        isa->iobase = isa_parallel_io[isa->index];
    index++;

    base = isa->iobase;
G
Gerd Hoffmann 已提交
497
    isa_init_irq(dev, &s->irq, isa->isairq);
498
    qemu_register_reset(parallel_reset, s);
499

500
    if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
501
        s->hw_driver = 1;
T
ths 已提交
502
        s->status = dummy;
503 504
    }

505 506 507 508 509
    isa_register_portio_list(dev, base,
                             (s->hw_driver
                              ? &isa_parallel_portio_hw_list[0]
                              : &isa_parallel_portio_sw_list[0]),
                             s, "parallel");
G
Gerd Hoffmann 已提交
510 511 512
    return 0;
}

513
/* Memory mapped interface */
A
Avi Kivity 已提交
514
static uint32_t parallel_mm_readb (void *opaque, hwaddr addr)
515 516 517
{
    ParallelState *s = opaque;

518
    return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFF;
519 520
}

521
static void parallel_mm_writeb (void *opaque,
A
Avi Kivity 已提交
522
                                hwaddr addr, uint32_t value)
523 524 525
{
    ParallelState *s = opaque;

526
    parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFF);
527 528
}

A
Avi Kivity 已提交
529
static uint32_t parallel_mm_readw (void *opaque, hwaddr addr)
530 531 532
{
    ParallelState *s = opaque;

533
    return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFFFF;
534 535
}

536
static void parallel_mm_writew (void *opaque,
A
Avi Kivity 已提交
537
                                hwaddr addr, uint32_t value)
538 539 540
{
    ParallelState *s = opaque;

541
    parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFFFF);
542 543
}

A
Avi Kivity 已提交
544
static uint32_t parallel_mm_readl (void *opaque, hwaddr addr)
545 546 547
{
    ParallelState *s = opaque;

548
    return parallel_ioport_read_sw(s, addr >> s->it_shift);
549 550
}

551
static void parallel_mm_writel (void *opaque,
A
Avi Kivity 已提交
552
                                hwaddr addr, uint32_t value)
553 554 555
{
    ParallelState *s = opaque;

556
    parallel_ioport_write_sw(s, addr >> s->it_shift, value);
557 558
}

A
Avi Kivity 已提交
559 560 561 562 563 564
static const MemoryRegionOps parallel_mm_ops = {
    .old_mmio = {
        .read = { parallel_mm_readb, parallel_mm_readw, parallel_mm_readl },
        .write = { parallel_mm_writeb, parallel_mm_writew, parallel_mm_writel },
    },
    .endianness = DEVICE_NATIVE_ENDIAN,
565 566 567
};

/* If fd is zero, it means that the parallel device uses the console */
A
Avi Kivity 已提交
568
bool parallel_mm_init(MemoryRegion *address_space,
A
Avi Kivity 已提交
569
                      hwaddr base, int it_shift, qemu_irq irq,
B
Blue Swirl 已提交
570
                      CharDriverState *chr)
571 572 573
{
    ParallelState *s;

574
    s = g_malloc0(sizeof(ParallelState));
A
aurel32 已提交
575 576
    s->irq = irq;
    s->chr = chr;
577
    s->it_shift = it_shift;
578
    qemu_register_reset(parallel_reset, s);
579

A
Avi Kivity 已提交
580 581 582
    memory_region_init_io(&s->iomem, &parallel_mm_ops, s,
                          "parallel", 8 << it_shift);
    memory_region_add_subregion(address_space, base, &s->iomem);
B
Blue Swirl 已提交
583
    return true;
584
}
G
Gerd Hoffmann 已提交
585

586 587 588 589 590 591 592 593
static Property parallel_isa_properties[] = {
    DEFINE_PROP_UINT32("index", ISAParallelState, index,   -1),
    DEFINE_PROP_HEX32("iobase", ISAParallelState, iobase,  -1),
    DEFINE_PROP_UINT32("irq",   ISAParallelState, isairq,  7),
    DEFINE_PROP_CHR("chardev",  ISAParallelState, state.chr),
    DEFINE_PROP_END_OF_LIST(),
};

594 595
static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
{
596
    DeviceClass *dc = DEVICE_CLASS(klass);
597 598
    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
    ic->init = parallel_isa_initfn;
599
    dc->props = parallel_isa_properties;
600 601
}

602
static const TypeInfo parallel_isa_info = {
603 604 605 606
    .name          = "isa-parallel",
    .parent        = TYPE_ISA_DEVICE,
    .instance_size = sizeof(ISAParallelState),
    .class_init    = parallel_isa_class_initfn,
G
Gerd Hoffmann 已提交
607 608
};

A
Andreas Färber 已提交
609
static void parallel_register_types(void)
G
Gerd Hoffmann 已提交
610
{
611
    type_register_static(&parallel_isa_info);
G
Gerd Hoffmann 已提交
612 613
}

A
Andreas Färber 已提交
614
type_init(parallel_register_types)