Annotation of qemu/hw/parallel.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  * QEMU Parallel PORT emulation
1.1.1.3   root        3:  *
1.1.1.2   root        4:  * Copyright (c) 2003-2005 Fabrice Bellard
1.1.1.3   root        5:  * Copyright (c) 2007 Marko Kohtala
                      6:  *
1.1       root        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:  */
1.1.1.3   root       25: #include "hw.h"
                     26: #include "qemu-char.h"
                     27: #include "isa.h"
                     28: #include "pc.h"
1.1       root       29: 
                     30: //#define DEBUG_PARALLEL
                     31: 
1.1.1.3   root       32: #ifdef DEBUG_PARALLEL
                     33: #define pdebug(fmt, arg...) printf("pp: " fmt, ##arg)
                     34: #else
                     35: #define pdebug(fmt, arg...) ((void)0)
                     36: #endif
                     37: 
                     38: #define PARA_REG_DATA 0
                     39: #define PARA_REG_STS 1
                     40: #define PARA_REG_CTR 2
                     41: #define PARA_REG_EPP_ADDR 3
                     42: #define PARA_REG_EPP_DATA 4
                     43: 
1.1       root       44: /*
                     45:  * These are the definitions for the Printer Status Register
                     46:  */
                     47: #define PARA_STS_BUSY  0x80    /* Busy complement */
                     48: #define PARA_STS_ACK   0x40    /* Acknowledge */
                     49: #define PARA_STS_PAPER 0x20    /* Out of paper */
                     50: #define PARA_STS_ONLINE        0x10    /* Online */
                     51: #define PARA_STS_ERROR 0x08    /* Error complement */
1.1.1.3   root       52: #define PARA_STS_TMOUT 0x01    /* EPP timeout */
1.1       root       53: 
                     54: /*
                     55:  * These are the definitions for the Printer Control Register
                     56:  */
1.1.1.3   root       57: #define PARA_CTR_DIR   0x20    /* Direction (1=read, 0=write) */
1.1       root       58: #define PARA_CTR_INTEN 0x10    /* IRQ Enable */
                     59: #define PARA_CTR_SELECT        0x08    /* Select In complement */
                     60: #define PARA_CTR_INIT  0x04    /* Initialize Printer complement */
                     61: #define PARA_CTR_AUTOLF        0x02    /* Auto linefeed complement */
                     62: #define PARA_CTR_STROBE        0x01    /* Strobe complement */
                     63: 
1.1.1.3   root       64: #define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
                     65: 
1.1       root       66: struct ParallelState {
1.1.1.3   root       67:     uint8_t dataw;
                     68:     uint8_t datar;
                     69:     uint8_t status;
1.1       root       70:     uint8_t control;
1.1.1.3   root       71:     qemu_irq irq;
1.1       root       72:     int irq_pending;
                     73:     CharDriverState *chr;
1.1.1.2   root       74:     int hw_driver;
1.1.1.3   root       75:     int epp_timeout;
                     76:     uint32_t last_read_offset; /* For debugging */
                     77:     /* Memory-mapped interface */
                     78:     int it_shift;
1.1       root       79: };
                     80: 
                     81: static void parallel_update_irq(ParallelState *s)
                     82: {
                     83:     if (s->irq_pending)
1.1.1.3   root       84:         qemu_irq_raise(s->irq);
1.1       root       85:     else
1.1.1.3   root       86:         qemu_irq_lower(s->irq);
1.1       root       87: }
                     88: 
1.1.1.3   root       89: static void
                     90: parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
1.1       root       91: {
                     92:     ParallelState *s = opaque;
1.1.1.3   root       93: 
                     94:     pdebug("write addr=0x%02x val=0x%02x\n", addr, val);
                     95: 
1.1       root       96:     addr &= 7;
                     97:     switch(addr) {
1.1.1.3   root       98:     case PARA_REG_DATA:
                     99:         s->dataw = val;
                    100:         parallel_update_irq(s);
                    101:         break;
                    102:     case PARA_REG_CTR:
1.1.1.4 ! root      103:         val |= 0xc0;
1.1.1.3   root      104:         if ((val & PARA_CTR_INIT) == 0 ) {
                    105:             s->status = PARA_STS_BUSY;
                    106:             s->status |= PARA_STS_ACK;
                    107:             s->status |= PARA_STS_ONLINE;
                    108:             s->status |= PARA_STS_ERROR;
                    109:         }
                    110:         else if (val & PARA_CTR_SELECT) {
                    111:             if (val & PARA_CTR_STROBE) {
                    112:                 s->status &= ~PARA_STS_BUSY;
                    113:                 if ((s->control & PARA_CTR_STROBE) == 0)
                    114:                     qemu_chr_write(s->chr, &s->dataw, 1);
                    115:             } else {
                    116:                 if (s->control & PARA_CTR_INTEN) {
                    117:                     s->irq_pending = 1;
1.1       root      118:                 }
                    119:             }
                    120:         }
1.1.1.3   root      121:         parallel_update_irq(s);
                    122:         s->control = val;
1.1       root      123:         break;
                    124:     }
                    125: }
                    126: 
1.1.1.3   root      127: static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
                    128: {
                    129:     ParallelState *s = opaque;
                    130:     uint8_t parm = val;
1.1.1.4 ! root      131:     int dir;
1.1.1.3   root      132: 
                    133:     /* Sometimes programs do several writes for timing purposes on old
                    134:        HW. Take care not to waste time on writes that do nothing. */
                    135: 
                    136:     s->last_read_offset = ~0U;
                    137: 
                    138:     addr &= 7;
                    139:     switch(addr) {
                    140:     case PARA_REG_DATA:
                    141:         if (s->dataw == val)
                    142:             return;
                    143:         pdebug("wd%02x\n", val);
                    144:         qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
                    145:         s->dataw = val;
                    146:         break;
                    147:     case PARA_REG_STS:
                    148:         pdebug("ws%02x\n", val);
                    149:         if (val & PARA_STS_TMOUT)
                    150:             s->epp_timeout = 0;
                    151:         break;
                    152:     case PARA_REG_CTR:
                    153:         val |= 0xc0;
                    154:         if (s->control == val)
                    155:             return;
                    156:         pdebug("wc%02x\n", val);
1.1.1.4 ! root      157: 
        !           158:         if ((val & PARA_CTR_DIR) != (s->control & PARA_CTR_DIR)) {
        !           159:             if (val & PARA_CTR_DIR) {
        !           160:                 dir = 1;
        !           161:             } else {
        !           162:                 dir = 0;
        !           163:             }
        !           164:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_DATA_DIR, &dir);
        !           165:             parm &= ~PARA_CTR_DIR;
        !           166:         }
        !           167: 
1.1.1.3   root      168:         qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
                    169:         s->control = val;
                    170:         break;
                    171:     case PARA_REG_EPP_ADDR:
                    172:         if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
                    173:             /* Controls not correct for EPP address cycle, so do nothing */
                    174:             pdebug("wa%02x s\n", val);
                    175:         else {
                    176:             struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
                    177:             if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
                    178:                 s->epp_timeout = 1;
                    179:                 pdebug("wa%02x t\n", val);
                    180:             }
                    181:             else
                    182:                 pdebug("wa%02x\n", val);
                    183:         }
                    184:         break;
                    185:     case PARA_REG_EPP_DATA:
                    186:         if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
                    187:             /* Controls not correct for EPP data cycle, so do nothing */
                    188:             pdebug("we%02x s\n", val);
                    189:         else {
                    190:             struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
                    191:             if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
                    192:                 s->epp_timeout = 1;
                    193:                 pdebug("we%02x t\n", val);
                    194:             }
                    195:             else
                    196:                 pdebug("we%02x\n", val);
                    197:         }
                    198:         break;
                    199:     }
                    200: }
                    201: 
                    202: static void
                    203: parallel_ioport_eppdata_write_hw2(void *opaque, uint32_t addr, uint32_t val)
                    204: {
                    205:     ParallelState *s = opaque;
                    206:     uint16_t eppdata = cpu_to_le16(val);
                    207:     int err;
                    208:     struct ParallelIOArg ioarg = {
                    209:         .buffer = &eppdata, .count = sizeof(eppdata)
                    210:     };
                    211:     if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
                    212:         /* Controls not correct for EPP data cycle, so do nothing */
                    213:         pdebug("we%04x s\n", val);
                    214:         return;
                    215:     }
                    216:     err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
                    217:     if (err) {
                    218:         s->epp_timeout = 1;
                    219:         pdebug("we%04x t\n", val);
                    220:     }
                    221:     else
                    222:         pdebug("we%04x\n", val);
                    223: }
                    224: 
                    225: static void
                    226: parallel_ioport_eppdata_write_hw4(void *opaque, uint32_t addr, uint32_t val)
                    227: {
                    228:     ParallelState *s = opaque;
                    229:     uint32_t eppdata = cpu_to_le32(val);
                    230:     int err;
                    231:     struct ParallelIOArg ioarg = {
                    232:         .buffer = &eppdata, .count = sizeof(eppdata)
                    233:     };
                    234:     if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
                    235:         /* Controls not correct for EPP data cycle, so do nothing */
                    236:         pdebug("we%08x s\n", val);
                    237:         return;
                    238:     }
                    239:     err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
                    240:     if (err) {
                    241:         s->epp_timeout = 1;
                    242:         pdebug("we%08x t\n", val);
                    243:     }
                    244:     else
                    245:         pdebug("we%08x\n", val);
                    246: }
                    247: 
                    248: static uint32_t parallel_ioport_read_sw(void *opaque, uint32_t addr)
1.1       root      249: {
                    250:     ParallelState *s = opaque;
                    251:     uint32_t ret = 0xff;
                    252: 
                    253:     addr &= 7;
                    254:     switch(addr) {
1.1.1.3   root      255:     case PARA_REG_DATA:
                    256:         if (s->control & PARA_CTR_DIR)
                    257:             ret = s->datar;
                    258:         else
                    259:             ret = s->dataw;
                    260:         break;
                    261:     case PARA_REG_STS:
                    262:         ret = s->status;
                    263:         s->irq_pending = 0;
                    264:         if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
                    265:             /* XXX Fixme: wait 5 microseconds */
                    266:             if (s->status & PARA_STS_ACK)
                    267:                 s->status &= ~PARA_STS_ACK;
                    268:             else {
1.1.1.2   root      269:                 /* XXX Fixme: wait 5 microseconds */
1.1.1.3   root      270:                 s->status |= PARA_STS_ACK;
                    271:                 s->status |= PARA_STS_BUSY;
1.1       root      272:             }
                    273:         }
1.1.1.3   root      274:         parallel_update_irq(s);
1.1       root      275:         break;
1.1.1.3   root      276:     case PARA_REG_CTR:
1.1       root      277:         ret = s->control;
                    278:         break;
                    279:     }
1.1.1.3   root      280:     pdebug("read addr=0x%02x val=0x%02x\n", addr, ret);
                    281:     return ret;
                    282: }
                    283: 
                    284: static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
                    285: {
                    286:     ParallelState *s = opaque;
                    287:     uint8_t ret = 0xff;
                    288:     addr &= 7;
                    289:     switch(addr) {
                    290:     case PARA_REG_DATA:
                    291:         qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
                    292:         if (s->last_read_offset != addr || s->datar != ret)
                    293:             pdebug("rd%02x\n", ret);
                    294:         s->datar = ret;
                    295:         break;
                    296:     case PARA_REG_STS:
                    297:         qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
                    298:         ret &= ~PARA_STS_TMOUT;
                    299:         if (s->epp_timeout)
                    300:             ret |= PARA_STS_TMOUT;
                    301:         if (s->last_read_offset != addr || s->status != ret)
                    302:             pdebug("rs%02x\n", ret);
                    303:         s->status = ret;
                    304:         break;
                    305:     case PARA_REG_CTR:
                    306:         /* s->control has some bits fixed to 1. It is zero only when
                    307:            it has not been yet written to.  */
                    308:         if (s->control == 0) {
                    309:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
                    310:             if (s->last_read_offset != addr)
                    311:                 pdebug("rc%02x\n", ret);
                    312:             s->control = ret;
                    313:         }
                    314:         else {
                    315:             ret = s->control;
                    316:             if (s->last_read_offset != addr)
                    317:                 pdebug("rc%02x\n", ret);
                    318:         }
                    319:         break;
                    320:     case PARA_REG_EPP_ADDR:
                    321:         if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
                    322:             /* Controls not correct for EPP addr cycle, so do nothing */
                    323:             pdebug("ra%02x s\n", ret);
                    324:         else {
                    325:             struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
                    326:             if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
                    327:                 s->epp_timeout = 1;
                    328:                 pdebug("ra%02x t\n", ret);
                    329:             }
                    330:             else
                    331:                 pdebug("ra%02x\n", ret);
                    332:         }
                    333:         break;
                    334:     case PARA_REG_EPP_DATA:
                    335:         if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
                    336:             /* Controls not correct for EPP data cycle, so do nothing */
                    337:             pdebug("re%02x s\n", ret);
                    338:         else {
                    339:             struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
                    340:             if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
                    341:                 s->epp_timeout = 1;
                    342:                 pdebug("re%02x t\n", ret);
                    343:             }
                    344:             else
                    345:                 pdebug("re%02x\n", ret);
                    346:         }
                    347:         break;
                    348:     }
                    349:     s->last_read_offset = addr;
1.1       root      350:     return ret;
                    351: }
                    352: 
1.1.1.3   root      353: static uint32_t
                    354: parallel_ioport_eppdata_read_hw2(void *opaque, uint32_t addr)
                    355: {
                    356:     ParallelState *s = opaque;
                    357:     uint32_t ret;
                    358:     uint16_t eppdata = ~0;
                    359:     int err;
                    360:     struct ParallelIOArg ioarg = {
                    361:         .buffer = &eppdata, .count = sizeof(eppdata)
                    362:     };
                    363:     if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
                    364:         /* Controls not correct for EPP data cycle, so do nothing */
                    365:         pdebug("re%04x s\n", eppdata);
                    366:         return eppdata;
                    367:     }
                    368:     err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
                    369:     ret = le16_to_cpu(eppdata);
                    370: 
                    371:     if (err) {
                    372:         s->epp_timeout = 1;
                    373:         pdebug("re%04x t\n", ret);
                    374:     }
                    375:     else
                    376:         pdebug("re%04x\n", ret);
                    377:     return ret;
                    378: }
                    379: 
                    380: static uint32_t
                    381: parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
                    382: {
                    383:     ParallelState *s = opaque;
                    384:     uint32_t ret;
                    385:     uint32_t eppdata = ~0U;
                    386:     int err;
                    387:     struct ParallelIOArg ioarg = {
                    388:         .buffer = &eppdata, .count = sizeof(eppdata)
                    389:     };
                    390:     if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
                    391:         /* Controls not correct for EPP data cycle, so do nothing */
                    392:         pdebug("re%08x s\n", eppdata);
                    393:         return eppdata;
                    394:     }
                    395:     err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
                    396:     ret = le32_to_cpu(eppdata);
                    397: 
                    398:     if (err) {
                    399:         s->epp_timeout = 1;
                    400:         pdebug("re%08x t\n", ret);
                    401:     }
                    402:     else
                    403:         pdebug("re%08x\n", ret);
                    404:     return ret;
                    405: }
                    406: 
                    407: static void parallel_ioport_ecp_write(void *opaque, uint32_t addr, uint32_t val)
                    408: {
                    409:     addr &= 7;
                    410:     pdebug("wecp%d=%02x\n", addr, val);
                    411: }
                    412: 
                    413: static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr)
                    414: {
                    415:     uint8_t ret = 0xff;
                    416:     addr &= 7;
                    417:     pdebug("recp%d:%02x\n", addr, ret);
                    418:     return ret;
                    419: }
                    420: 
1.1.1.4 ! root      421: static void parallel_reset(void *opaque)
1.1.1.3   root      422: {
1.1.1.4 ! root      423:     ParallelState *s = opaque;
        !           424: 
1.1.1.3   root      425:     s->datar = ~0;
                    426:     s->dataw = ~0;
                    427:     s->status = PARA_STS_BUSY;
                    428:     s->status |= PARA_STS_ACK;
                    429:     s->status |= PARA_STS_ONLINE;
                    430:     s->status |= PARA_STS_ERROR;
1.1.1.4 ! root      431:     s->status |= PARA_STS_TMOUT;
1.1.1.3   root      432:     s->control = PARA_CTR_SELECT;
                    433:     s->control |= PARA_CTR_INIT;
1.1.1.4 ! root      434:     s->control |= 0xc0;
1.1.1.3   root      435:     s->irq_pending = 0;
                    436:     s->hw_driver = 0;
                    437:     s->epp_timeout = 0;
                    438:     s->last_read_offset = ~0U;
                    439: }
                    440: 
1.1       root      441: /* If fd is zero, it means that the parallel device uses the console */
1.1.1.3   root      442: ParallelState *parallel_init(int base, qemu_irq irq, CharDriverState *chr)
1.1       root      443: {
                    444:     ParallelState *s;
1.1.1.2   root      445:     uint8_t dummy;
1.1       root      446: 
                    447:     s = qemu_mallocz(sizeof(ParallelState));
1.1.1.4 ! root      448:     s->irq = irq;
        !           449:     s->chr = chr;
        !           450:     parallel_reset(s);
        !           451:     qemu_register_reset(parallel_reset, s);
1.1.1.3   root      452: 
                    453:     if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
1.1.1.2   root      454:         s->hw_driver = 1;
1.1.1.3   root      455:         s->status = dummy;
                    456:     }
1.1.1.2   root      457: 
1.1.1.3   root      458:     if (s->hw_driver) {
                    459:         register_ioport_write(base, 8, 1, parallel_ioport_write_hw, s);
                    460:         register_ioport_read(base, 8, 1, parallel_ioport_read_hw, s);
                    461:         register_ioport_write(base+4, 1, 2, parallel_ioport_eppdata_write_hw2, s);
                    462:         register_ioport_read(base+4, 1, 2, parallel_ioport_eppdata_read_hw2, s);
                    463:         register_ioport_write(base+4, 1, 4, parallel_ioport_eppdata_write_hw4, s);
                    464:         register_ioport_read(base+4, 1, 4, parallel_ioport_eppdata_read_hw4, s);
                    465:         register_ioport_write(base+0x400, 8, 1, parallel_ioport_ecp_write, s);
                    466:         register_ioport_read(base+0x400, 8, 1, parallel_ioport_ecp_read, s);
                    467:     }
                    468:     else {
                    469:         register_ioport_write(base, 8, 1, parallel_ioport_write_sw, s);
                    470:         register_ioport_read(base, 8, 1, parallel_ioport_read_sw, s);
                    471:     }
                    472:     return s;
                    473: }
                    474: 
                    475: /* Memory mapped interface */
                    476: static uint32_t parallel_mm_readb (void *opaque, target_phys_addr_t addr)
                    477: {
                    478:     ParallelState *s = opaque;
                    479: 
1.1.1.4 ! root      480:     return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFF;
1.1.1.3   root      481: }
                    482: 
                    483: static void parallel_mm_writeb (void *opaque,
                    484:                                 target_phys_addr_t addr, uint32_t value)
                    485: {
                    486:     ParallelState *s = opaque;
                    487: 
1.1.1.4 ! root      488:     parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFF);
1.1.1.3   root      489: }
                    490: 
                    491: static uint32_t parallel_mm_readw (void *opaque, target_phys_addr_t addr)
                    492: {
                    493:     ParallelState *s = opaque;
                    494: 
1.1.1.4 ! root      495:     return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFFFF;
1.1.1.3   root      496: }
                    497: 
                    498: static void parallel_mm_writew (void *opaque,
                    499:                                 target_phys_addr_t addr, uint32_t value)
                    500: {
                    501:     ParallelState *s = opaque;
                    502: 
1.1.1.4 ! root      503:     parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFFFF);
1.1.1.3   root      504: }
                    505: 
                    506: static uint32_t parallel_mm_readl (void *opaque, target_phys_addr_t addr)
                    507: {
                    508:     ParallelState *s = opaque;
                    509: 
1.1.1.4 ! root      510:     return parallel_ioport_read_sw(s, addr >> s->it_shift);
1.1.1.3   root      511: }
                    512: 
                    513: static void parallel_mm_writel (void *opaque,
                    514:                                 target_phys_addr_t addr, uint32_t value)
                    515: {
                    516:     ParallelState *s = opaque;
                    517: 
1.1.1.4 ! root      518:     parallel_ioport_write_sw(s, addr >> s->it_shift, value);
1.1.1.3   root      519: }
                    520: 
                    521: static CPUReadMemoryFunc *parallel_mm_read_sw[] = {
                    522:     &parallel_mm_readb,
                    523:     &parallel_mm_readw,
                    524:     &parallel_mm_readl,
                    525: };
                    526: 
                    527: static CPUWriteMemoryFunc *parallel_mm_write_sw[] = {
                    528:     &parallel_mm_writeb,
                    529:     &parallel_mm_writew,
                    530:     &parallel_mm_writel,
                    531: };
                    532: 
                    533: /* If fd is zero, it means that the parallel device uses the console */
                    534: ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, CharDriverState *chr)
                    535: {
                    536:     ParallelState *s;
                    537:     int io_sw;
                    538: 
                    539:     s = qemu_mallocz(sizeof(ParallelState));
1.1.1.4 ! root      540:     s->irq = irq;
        !           541:     s->chr = chr;
1.1.1.3   root      542:     s->it_shift = it_shift;
1.1.1.4 ! root      543:     parallel_reset(s);
        !           544:     qemu_register_reset(parallel_reset, s);
1.1       root      545: 
1.1.1.3   root      546:     io_sw = cpu_register_io_memory(0, parallel_mm_read_sw, parallel_mm_write_sw, s);
                    547:     cpu_register_physical_memory(base, 8 << it_shift, io_sw);
1.1       root      548:     return s;
                    549: }

unix.superglobalmegacorp.com