Statistics
| Branch: | Revision:

root / hw / parallel.c @ 26a76461

History | View | Annotate | Download (5.6 kB)

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