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

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

unix.superglobalmegacorp.com