Statistics
| Branch: | Revision:

root / hw / parallel.c @ dc9543dc

History | View | Annotate | Download (5.2 kB)

1 6508fe59 bellard
/*
2 6508fe59 bellard
 * QEMU Parallel PORT emulation
3 6508fe59 bellard
 * 
4 6508fe59 bellard
 * Copyright (c) 2003-2004 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 6508fe59 bellard
};
54 6508fe59 bellard
55 6508fe59 bellard
static void parallel_update_irq(ParallelState *s)
56 6508fe59 bellard
{
57 6508fe59 bellard
    if (s->irq_pending)
58 6508fe59 bellard
        pic_set_irq(s->irq, 1);
59 6508fe59 bellard
    else
60 6508fe59 bellard
        pic_set_irq(s->irq, 0);
61 6508fe59 bellard
}
62 6508fe59 bellard
63 6508fe59 bellard
static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
64 6508fe59 bellard
{
65 6508fe59 bellard
    ParallelState *s = opaque;
66 6508fe59 bellard
    
67 6508fe59 bellard
    addr &= 7;
68 6508fe59 bellard
#ifdef DEBUG_PARALLEL
69 6508fe59 bellard
    printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
70 6508fe59 bellard
#endif
71 6508fe59 bellard
    switch(addr) {
72 6508fe59 bellard
    case 0:
73 6508fe59 bellard
        s->data = val;
74 6508fe59 bellard
        parallel_update_irq(s);
75 6508fe59 bellard
        break;
76 6508fe59 bellard
    case 2:
77 6508fe59 bellard
        if ((val & PARA_CTR_INIT) == 0 ) {
78 6508fe59 bellard
            s->status = PARA_STS_BUSY;
79 6508fe59 bellard
            s->status |= PARA_STS_ACK;
80 6508fe59 bellard
            s->status |= PARA_STS_ONLINE;
81 6508fe59 bellard
            s->status |= PARA_STS_ERROR;
82 6508fe59 bellard
        }
83 6508fe59 bellard
        else if (val & PARA_CTR_SELECT) {
84 6508fe59 bellard
            if (val & PARA_CTR_STROBE) {
85 6508fe59 bellard
                s->status &= ~PARA_STS_BUSY;
86 6508fe59 bellard
                if ((s->control & PARA_CTR_STROBE) == 0)
87 6508fe59 bellard
                    qemu_chr_write(s->chr, &s->data, 1);
88 6508fe59 bellard
            } else {
89 6508fe59 bellard
                if (s->control & PARA_CTR_INTEN) {
90 6508fe59 bellard
                    s->irq_pending = 1;
91 6508fe59 bellard
                }
92 6508fe59 bellard
            }
93 6508fe59 bellard
        }
94 6508fe59 bellard
        parallel_update_irq(s);
95 6508fe59 bellard
        s->control = val;
96 6508fe59 bellard
        break;
97 6508fe59 bellard
    }
98 6508fe59 bellard
}
99 6508fe59 bellard
100 6508fe59 bellard
static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
101 6508fe59 bellard
{
102 6508fe59 bellard
    ParallelState *s = opaque;
103 6508fe59 bellard
    uint32_t ret = 0xff;
104 6508fe59 bellard
105 6508fe59 bellard
    addr &= 7;
106 6508fe59 bellard
    switch(addr) {
107 6508fe59 bellard
    case 0:
108 6508fe59 bellard
        ret = s->data; 
109 6508fe59 bellard
        break;
110 6508fe59 bellard
    case 1:
111 6508fe59 bellard
        ret = s->status;
112 6508fe59 bellard
        s->irq_pending = 0;
113 6508fe59 bellard
        if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
114 6508fe59 bellard
            /* XXX Fixme: wait 5 microseconds */
115 6508fe59 bellard
            if (s->status & PARA_STS_ACK)
116 6508fe59 bellard
                s->status &= ~PARA_STS_ACK;
117 6508fe59 bellard
            else {
118 6508fe59 bellard
            /* XXX Fixme: wait 5 microseconds */
119 6508fe59 bellard
                s->status |= PARA_STS_ACK;
120 6508fe59 bellard
                s->status |= PARA_STS_BUSY;
121 6508fe59 bellard
            }
122 6508fe59 bellard
        }
123 6508fe59 bellard
        parallel_update_irq(s);
124 6508fe59 bellard
        break;
125 6508fe59 bellard
    case 2:
126 6508fe59 bellard
        ret = s->control;
127 6508fe59 bellard
        break;
128 6508fe59 bellard
    }
129 6508fe59 bellard
#ifdef DEBUG_PARALLEL
130 6508fe59 bellard
    printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
131 6508fe59 bellard
#endif
132 6508fe59 bellard
    return ret;
133 6508fe59 bellard
}
134 6508fe59 bellard
135 6508fe59 bellard
static int parallel_can_receive(ParallelState *s)
136 6508fe59 bellard
{
137 6508fe59 bellard
    return 0;
138 6508fe59 bellard
}
139 6508fe59 bellard
140 6508fe59 bellard
static void parallel_receive_byte(ParallelState *s, int ch)
141 6508fe59 bellard
{
142 6508fe59 bellard
}
143 6508fe59 bellard
144 6508fe59 bellard
static int parallel_can_receive1(void *opaque)
145 6508fe59 bellard
{
146 6508fe59 bellard
    ParallelState *s = opaque;
147 6508fe59 bellard
    return parallel_can_receive(s);
148 6508fe59 bellard
}
149 6508fe59 bellard
150 6508fe59 bellard
static void parallel_receive1(void *opaque, const uint8_t *buf, int size)
151 6508fe59 bellard
{
152 6508fe59 bellard
    ParallelState *s = opaque;
153 6508fe59 bellard
    parallel_receive_byte(s, buf[0]);
154 6508fe59 bellard
}
155 6508fe59 bellard
156 6508fe59 bellard
static void parallel_event(void *opaque, int event)
157 6508fe59 bellard
{
158 6508fe59 bellard
}
159 6508fe59 bellard
160 6508fe59 bellard
/* If fd is zero, it means that the parallel device uses the console */
161 6508fe59 bellard
ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
162 6508fe59 bellard
{
163 6508fe59 bellard
    ParallelState *s;
164 6508fe59 bellard
165 6508fe59 bellard
    s = qemu_mallocz(sizeof(ParallelState));
166 6508fe59 bellard
    if (!s)
167 6508fe59 bellard
        return NULL;
168 6508fe59 bellard
    s->irq = irq;
169 6508fe59 bellard
    s->data = 0;
170 6508fe59 bellard
    s->status = PARA_STS_BUSY;
171 6508fe59 bellard
    s->status |= PARA_STS_ACK;
172 6508fe59 bellard
    s->status |= PARA_STS_ONLINE;
173 6508fe59 bellard
    s->status |= PARA_STS_ERROR;
174 6508fe59 bellard
    s->control = PARA_CTR_SELECT;
175 6508fe59 bellard
    s->control |= PARA_CTR_INIT;
176 6508fe59 bellard
177 6508fe59 bellard
    register_ioport_write(base, 8, 1, parallel_ioport_write, s);
178 6508fe59 bellard
    register_ioport_read(base, 8, 1, parallel_ioport_read, s);
179 6508fe59 bellard
    s->chr = chr;
180 6508fe59 bellard
    qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s);
181 6508fe59 bellard
    qemu_chr_add_event_handler(chr, parallel_event);
182 6508fe59 bellard
    return s;
183 6508fe59 bellard
}