Revision e4a89056 hw/slavio_serial.c
b/hw/slavio_serial.c | ||
---|---|---|
88 | 88 |
typedef struct ChannelState { |
89 | 89 |
int irq; |
90 | 90 |
int reg; |
91 |
int rxint, txint; |
|
91 |
int rxint, txint, rxint_under_svc, txint_under_svc;
|
|
92 | 92 |
chn_id_t chn; // this channel, A (base+4) or B (base+0) |
93 | 93 |
chn_type_t type; |
94 | 94 |
struct ChannelState *otherchn; |
... | ... | |
106 | 106 |
static void handle_kbd_command(ChannelState *s, int val); |
107 | 107 |
static int serial_can_receive(void *opaque); |
108 | 108 |
static void serial_receive_byte(ChannelState *s, int ch); |
109 |
static inline void set_txint(ChannelState *s); |
|
109 | 110 |
|
110 | 111 |
static void put_queue(void *opaque, int b) |
111 | 112 |
{ |
... | ... | |
142 | 143 |
return val; |
143 | 144 |
} |
144 | 145 |
|
145 |
static void slavio_serial_update_irq(ChannelState *s)
|
|
146 |
static int slavio_serial_update_irq_chn(ChannelState *s)
|
|
146 | 147 |
{ |
147 | 148 |
if ((s->wregs[1] & 1) && // interrupts enabled |
148 | 149 |
(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending |
149 | 150 |
((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) && |
150 | 151 |
s->rxint == 1) || // rx ints enabled, pending |
151 | 152 |
((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p |
152 |
pic_set_irq(s->irq, 1); |
|
153 |
} else { |
|
154 |
pic_set_irq(s->irq, 0); |
|
153 |
return 1; |
|
155 | 154 |
} |
155 |
return 0; |
|
156 |
} |
|
157 |
|
|
158 |
static void slavio_serial_update_irq(ChannelState *s) |
|
159 |
{ |
|
160 |
int irq; |
|
161 |
|
|
162 |
irq = slavio_serial_update_irq_chn(s); |
|
163 |
irq |= slavio_serial_update_irq_chn(s->otherchn); |
|
164 |
|
|
165 |
pic_set_irq(s->irq, irq); |
|
156 | 166 |
} |
157 | 167 |
|
158 | 168 |
static void slavio_serial_reset_chn(ChannelState *s) |
... | ... | |
174 | 184 |
|
175 | 185 |
s->rx = s->tx = 0; |
176 | 186 |
s->rxint = s->txint = 0; |
187 |
s->rxint_under_svc = s->txint_under_svc = 0; |
|
177 | 188 |
} |
178 | 189 |
|
179 | 190 |
static void slavio_serial_reset(void *opaque) |
... | ... | |
186 | 197 |
static inline void clr_rxint(ChannelState *s) |
187 | 198 |
{ |
188 | 199 |
s->rxint = 0; |
200 |
s->rxint_under_svc = 0; |
|
189 | 201 |
if (s->chn == 0) |
190 | 202 |
s->rregs[3] &= ~0x20; |
191 | 203 |
else { |
192 | 204 |
s->otherchn->rregs[3] &= ~4; |
193 | 205 |
} |
206 |
if (s->txint) |
|
207 |
set_txint(s); |
|
208 |
else |
|
209 |
s->rregs[2] = 6; |
|
194 | 210 |
slavio_serial_update_irq(s); |
195 | 211 |
} |
196 | 212 |
|
197 | 213 |
static inline void set_rxint(ChannelState *s) |
198 | 214 |
{ |
199 | 215 |
s->rxint = 1; |
200 |
if (s->chn == 0) |
|
201 |
s->rregs[3] |= 0x20; |
|
202 |
else { |
|
203 |
s->otherchn->rregs[3] |= 4; |
|
216 |
if (!s->txint_under_svc) { |
|
217 |
s->rxint_under_svc = 1; |
|
218 |
if (s->chn == 0) |
|
219 |
s->rregs[3] |= 0x20; |
|
220 |
else { |
|
221 |
s->otherchn->rregs[3] |= 4; |
|
222 |
} |
|
223 |
s->rregs[2] = 4; |
|
224 |
slavio_serial_update_irq(s); |
|
204 | 225 |
} |
205 |
slavio_serial_update_irq(s); |
|
206 | 226 |
} |
207 | 227 |
|
208 | 228 |
static inline void clr_txint(ChannelState *s) |
209 | 229 |
{ |
210 | 230 |
s->txint = 0; |
231 |
s->txint_under_svc = 0; |
|
211 | 232 |
if (s->chn == 0) |
212 | 233 |
s->rregs[3] &= ~0x10; |
213 | 234 |
else { |
214 | 235 |
s->otherchn->rregs[3] &= ~2; |
215 | 236 |
} |
237 |
if (s->rxint) |
|
238 |
set_rxint(s); |
|
239 |
else |
|
240 |
s->rregs[2] = 6; |
|
216 | 241 |
slavio_serial_update_irq(s); |
217 | 242 |
} |
218 | 243 |
|
219 | 244 |
static inline void set_txint(ChannelState *s) |
220 | 245 |
{ |
221 | 246 |
s->txint = 1; |
222 |
if (s->chn == 0) |
|
223 |
s->rregs[3] |= 0x10; |
|
224 |
else { |
|
225 |
s->otherchn->rregs[3] |= 2; |
|
247 |
if (!s->rxint_under_svc) { |
|
248 |
s->txint_under_svc = 1; |
|
249 |
if (s->chn == 0) |
|
250 |
s->rregs[3] |= 0x10; |
|
251 |
else { |
|
252 |
s->otherchn->rregs[3] |= 2; |
|
253 |
} |
|
254 |
s->rregs[2] = 0; |
|
255 |
slavio_serial_update_irq(s); |
|
226 | 256 |
} |
227 |
slavio_serial_update_irq(s); |
|
228 | 257 |
} |
229 | 258 |
|
230 | 259 |
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
... | ... | |
250 | 279 |
case 8: |
251 | 280 |
newreg |= 0x8; |
252 | 281 |
break; |
253 |
case 0x20: |
|
254 |
clr_rxint(s); |
|
255 |
break; |
|
256 | 282 |
case 0x28: |
257 | 283 |
clr_txint(s); |
258 | 284 |
break; |
259 | 285 |
case 0x38: |
260 |
clr_rxint(s); |
|
261 |
clr_txint(s); |
|
286 |
if (s->rxint_under_svc) |
|
287 |
clr_rxint(s); |
|
288 |
else if (s->txint_under_svc) |
|
289 |
clr_txint(s); |
|
262 | 290 |
break; |
263 | 291 |
default: |
264 | 292 |
break; |
... | ... | |
301 | 329 |
else if (s->type == kbd) { |
302 | 330 |
handle_kbd_command(s, val); |
303 | 331 |
} |
304 |
s->txint = 1; |
|
305 | 332 |
s->rregs[0] |= 4; // Tx buffer empty |
306 | 333 |
s->rregs[1] |= 1; // All sent |
307 | 334 |
set_txint(s); |
308 |
slavio_serial_update_irq(s); |
|
309 | 335 |
} |
310 | 336 |
break; |
311 | 337 |
default: |
... | ... | |
348 | 374 |
static int serial_can_receive(void *opaque) |
349 | 375 |
{ |
350 | 376 |
ChannelState *s = opaque; |
377 |
int ret; |
|
378 |
|
|
351 | 379 |
if (((s->wregs[3] & 1) == 0) // Rx not enabled |
352 | 380 |
|| ((s->rregs[0] & 1) == 1)) // char already available |
353 |
return 0;
|
|
381 |
ret = 0;
|
|
354 | 382 |
else |
355 |
return 1; |
|
383 |
ret = 1; |
|
384 |
SER_DPRINTF("can receive %d\n", ret); |
|
385 |
return ret; |
|
356 | 386 |
} |
357 | 387 |
|
358 | 388 |
static void serial_receive_byte(ChannelState *s, int ch) |
... | ... | |
400 | 430 |
qemu_put_be32s(f, &s->reg); |
401 | 431 |
qemu_put_be32s(f, &s->rxint); |
402 | 432 |
qemu_put_be32s(f, &s->txint); |
433 |
qemu_put_be32s(f, &s->rxint_under_svc); |
|
434 |
qemu_put_be32s(f, &s->txint_under_svc); |
|
403 | 435 |
qemu_put_8s(f, &s->rx); |
404 | 436 |
qemu_put_8s(f, &s->tx); |
405 | 437 |
qemu_put_buffer(f, s->wregs, 16); |
... | ... | |
416 | 448 |
|
417 | 449 |
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id) |
418 | 450 |
{ |
419 |
if (version_id != 1)
|
|
451 |
if (version_id > 2)
|
|
420 | 452 |
return -EINVAL; |
421 | 453 |
|
422 | 454 |
qemu_get_be32s(f, &s->irq); |
423 | 455 |
qemu_get_be32s(f, &s->reg); |
424 | 456 |
qemu_get_be32s(f, &s->rxint); |
425 | 457 |
qemu_get_be32s(f, &s->txint); |
458 |
if (version_id >= 2) { |
|
459 |
qemu_get_be32s(f, &s->rxint_under_svc); |
|
460 |
qemu_get_be32s(f, &s->txint_under_svc); |
|
461 |
} |
|
426 | 462 |
qemu_get_8s(f, &s->rx); |
427 | 463 |
qemu_get_8s(f, &s->tx); |
428 | 464 |
qemu_get_buffer(f, s->wregs, 16); |
... | ... | |
469 | 505 |
} |
470 | 506 |
s->chn[0].otherchn = &s->chn[1]; |
471 | 507 |
s->chn[1].otherchn = &s->chn[0]; |
472 |
register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
|
|
508 |
register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s);
|
|
473 | 509 |
qemu_register_reset(slavio_serial_reset, s); |
474 | 510 |
slavio_serial_reset(s); |
475 | 511 |
return s; |
... | ... | |
519 | 555 |
ChannelState *s = opaque; |
520 | 556 |
int ch; |
521 | 557 |
|
558 |
/* XXX: SDL sometimes generates nul events: we delete them */ |
|
559 |
if (dx == 0 && dy == 0 && dz == 0 && buttons_state == 0) |
|
560 |
return; |
|
522 | 561 |
MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state); |
523 | 562 |
|
524 | 563 |
ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */ |
Also available in: Unified diff