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

1.1       root        1: /*
                      2:  * QEMU Parallel PORT emulation
                      3:  * 
1.1.1.2 ! root        4:  * Copyright (c) 2003-2005 Fabrice Bellard
1.1       root        5:  * 
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include "vl.h"
                     25: 
                     26: //#define DEBUG_PARALLEL
                     27: 
                     28: /*
                     29:  * These are the definitions for the Printer Status Register
                     30:  */
                     31: #define PARA_STS_BUSY  0x80    /* Busy complement */
                     32: #define PARA_STS_ACK   0x40    /* Acknowledge */
                     33: #define PARA_STS_PAPER 0x20    /* Out of paper */
                     34: #define PARA_STS_ONLINE        0x10    /* Online */
                     35: #define PARA_STS_ERROR 0x08    /* Error complement */
                     36: 
                     37: /*
                     38:  * These are the definitions for the Printer Control Register
                     39:  */
                     40: #define PARA_CTR_INTEN 0x10    /* IRQ Enable */
                     41: #define PARA_CTR_SELECT        0x08    /* Select In complement */
                     42: #define PARA_CTR_INIT  0x04    /* Initialize Printer complement */
                     43: #define PARA_CTR_AUTOLF        0x02    /* Auto linefeed complement */
                     44: #define PARA_CTR_STROBE        0x01    /* Strobe complement */
                     45: 
                     46: struct ParallelState {
                     47:     uint8_t data;
                     48:     uint8_t status; /* read only register */
                     49:     uint8_t control;
                     50:     int irq;
                     51:     int irq_pending;
                     52:     CharDriverState *chr;
1.1.1.2 ! root       53:     int hw_driver;
1.1       root       54: };
                     55: 
                     56: static void parallel_update_irq(ParallelState *s)
                     57: {
                     58:     if (s->irq_pending)
                     59:         pic_set_irq(s->irq, 1);
                     60:     else
                     61:         pic_set_irq(s->irq, 0);
                     62: }
                     63: 
                     64: static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                     65: {
                     66:     ParallelState *s = opaque;
                     67:     
                     68:     addr &= 7;
                     69: #ifdef DEBUG_PARALLEL
                     70:     printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
                     71: #endif
                     72:     switch(addr) {
                     73:     case 0:
1.1.1.2 ! root       74:         if (s->hw_driver) {
        !            75:             s->data = val;
        !            76:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &s->data);
        !            77:         } else {
        !            78:             s->data = val;
        !            79:             parallel_update_irq(s);
        !            80:         }
1.1       root       81:         break;
                     82:     case 2:
1.1.1.2 ! root       83:         if (s->hw_driver) {
        !            84:             s->control = val;
        !            85:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &s->control);
        !            86:         } else {
        !            87:             if ((val & PARA_CTR_INIT) == 0 ) {
        !            88:                 s->status = PARA_STS_BUSY;
        !            89:                 s->status |= PARA_STS_ACK;
        !            90:                 s->status |= PARA_STS_ONLINE;
        !            91:                 s->status |= PARA_STS_ERROR;
        !            92:             }
        !            93:             else if (val & PARA_CTR_SELECT) {
        !            94:                 if (val & PARA_CTR_STROBE) {
        !            95:                     s->status &= ~PARA_STS_BUSY;
        !            96:                     if ((s->control & PARA_CTR_STROBE) == 0)
        !            97:                         qemu_chr_write(s->chr, &s->data, 1);
        !            98:                 } else {
        !            99:                     if (s->control & PARA_CTR_INTEN) {
        !           100:                         s->irq_pending = 1;
        !           101:                     }
1.1       root      102:                 }
                    103:             }
1.1.1.2 ! root      104:             parallel_update_irq(s);
        !           105:             s->control = val;
1.1       root      106:         }
                    107:         break;
                    108:     }
                    109: }
                    110: 
                    111: static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
                    112: {
                    113:     ParallelState *s = opaque;
                    114:     uint32_t ret = 0xff;
                    115: 
                    116:     addr &= 7;
                    117:     switch(addr) {
                    118:     case 0:
1.1.1.2 ! root      119:         if (s->hw_driver) {
        !           120:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
        !           121:         } 
1.1       root      122:         ret = s->data; 
                    123:         break;
                    124:     case 1:
1.1.1.2 ! root      125:         if (s->hw_driver) {
        !           126:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &s->status);
        !           127:             ret = s->status; 
        !           128:         } else {
        !           129:             ret = s->status;
        !           130:             s->irq_pending = 0;
        !           131:             if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
        !           132:                 /* XXX Fixme: wait 5 microseconds */
        !           133:                 if (s->status & PARA_STS_ACK)
        !           134:                     s->status &= ~PARA_STS_ACK;
        !           135:                 else {
        !           136:                     /* XXX Fixme: wait 5 microseconds */
        !           137:                     s->status |= PARA_STS_ACK;
        !           138:                     s->status |= PARA_STS_BUSY;
        !           139:                 }
1.1       root      140:             }
1.1.1.2 ! root      141:             parallel_update_irq(s);
1.1       root      142:         }
                    143:         break;
                    144:     case 2:
1.1.1.2 ! root      145:         if (s->hw_driver) {
        !           146:             qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
        !           147:         }
1.1       root      148:         ret = s->control;
                    149:         break;
                    150:     }
                    151: #ifdef DEBUG_PARALLEL
                    152:     printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
                    153: #endif
                    154:     return ret;
                    155: }
                    156: 
                    157: /* If fd is zero, it means that the parallel device uses the console */
                    158: ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
                    159: {
                    160:     ParallelState *s;
1.1.1.2 ! root      161:     uint8_t dummy;
1.1       root      162: 
                    163:     s = qemu_mallocz(sizeof(ParallelState));
                    164:     if (!s)
                    165:         return NULL;
1.1.1.2 ! root      166:     s->chr = chr;
        !           167:     s->hw_driver = 0;
        !           168:     if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0)
        !           169:         s->hw_driver = 1;
        !           170: 
1.1       root      171:     s->irq = irq;
                    172:     s->data = 0;
                    173:     s->status = PARA_STS_BUSY;
                    174:     s->status |= PARA_STS_ACK;
                    175:     s->status |= PARA_STS_ONLINE;
                    176:     s->status |= PARA_STS_ERROR;
                    177:     s->control = PARA_CTR_SELECT;
                    178:     s->control |= PARA_CTR_INIT;
                    179: 
                    180:     register_ioport_write(base, 8, 1, parallel_ioport_write, s);
                    181:     register_ioport_read(base, 8, 1, parallel_ioport_read, s);
                    182:     return s;
                    183: }

unix.superglobalmegacorp.com