Revision f930d07e hw/slavio_serial.c
b/hw/slavio_serial.c | ||
---|---|---|
139 | 139 |
int val; |
140 | 140 |
|
141 | 141 |
if (q->count == 0) { |
142 |
return 0;
|
|
142 |
return 0;
|
|
143 | 143 |
} else { |
144 | 144 |
val = q->data[q->rptr]; |
145 | 145 |
if (++q->rptr == SERIO_QUEUE_SIZE) |
... | ... | |
148 | 148 |
} |
149 | 149 |
SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val); |
150 | 150 |
if (q->count > 0) |
151 |
serial_receive_byte(s, 0);
|
|
151 |
serial_receive_byte(s, 0);
|
|
152 | 152 |
return val; |
153 | 153 |
} |
154 | 154 |
|
155 | 155 |
static int slavio_serial_update_irq_chn(ChannelState *s) |
156 | 156 |
{ |
157 | 157 |
if ((s->wregs[1] & 1) && // interrupts enabled |
158 |
(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
|
|
159 |
((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
|
|
160 |
s->rxint == 1) || // rx ints enabled, pending
|
|
161 |
((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
|
|
158 |
(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
|
|
159 |
((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
|
|
160 |
s->rxint == 1) || // rx ints enabled, pending
|
|
161 |
((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
|
|
162 | 162 |
return 1; |
163 | 163 |
} |
164 | 164 |
return 0; |
... | ... | |
181 | 181 |
|
182 | 182 |
s->reg = 0; |
183 | 183 |
for (i = 0; i < SERIAL_SIZE; i++) { |
184 |
s->rregs[i] = 0;
|
|
185 |
s->wregs[i] = 0;
|
|
184 |
s->rregs[i] = 0;
|
|
185 |
s->wregs[i] = 0;
|
|
186 | 186 |
} |
187 | 187 |
s->wregs[4] = 4; |
188 | 188 |
s->wregs[9] = 0xc0; |
... | ... | |
367 | 367 |
s = &serial->chn[channel]; |
368 | 368 |
switch (saddr) { |
369 | 369 |
case 0: |
370 |
SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
|
|
371 |
newreg = 0;
|
|
372 |
switch (s->reg) {
|
|
373 |
case 0:
|
|
374 |
newreg = val & 7;
|
|
375 |
val &= 0x38;
|
|
376 |
switch (val) {
|
|
377 |
case 8:
|
|
378 |
newreg |= 0x8;
|
|
379 |
break;
|
|
380 |
case 0x28:
|
|
370 |
SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
|
|
371 |
newreg = 0;
|
|
372 |
switch (s->reg) {
|
|
373 |
case 0:
|
|
374 |
newreg = val & 7;
|
|
375 |
val &= 0x38;
|
|
376 |
switch (val) {
|
|
377 |
case 8:
|
|
378 |
newreg |= 0x8;
|
|
379 |
break;
|
|
380 |
case 0x28:
|
|
381 | 381 |
clr_txint(s); |
382 |
break;
|
|
383 |
case 0x38:
|
|
382 |
break;
|
|
383 |
case 0x38:
|
|
384 | 384 |
if (s->rxint_under_svc) |
385 | 385 |
clr_rxint(s); |
386 | 386 |
else if (s->txint_under_svc) |
387 | 387 |
clr_txint(s); |
388 |
break;
|
|
389 |
default:
|
|
390 |
break;
|
|
391 |
}
|
|
392 |
break;
|
|
388 |
break;
|
|
389 |
default:
|
|
390 |
break;
|
|
391 |
}
|
|
392 |
break;
|
|
393 | 393 |
case 1 ... 3: |
394 | 394 |
case 6 ... 8: |
395 | 395 |
case 10 ... 11: |
396 | 396 |
case 14 ... 15: |
397 |
s->wregs[s->reg] = val;
|
|
398 |
break;
|
|
397 |
s->wregs[s->reg] = val;
|
|
398 |
break;
|
|
399 | 399 |
case 4: |
400 | 400 |
case 5: |
401 | 401 |
case 12: |
402 | 402 |
case 13: |
403 |
s->wregs[s->reg] = val;
|
|
403 |
s->wregs[s->reg] = val;
|
|
404 | 404 |
slavio_serial_update_parameters(s); |
405 |
break;
|
|
406 |
case 9:
|
|
407 |
switch (val & 0xc0) {
|
|
408 |
case 0:
|
|
409 |
default:
|
|
410 |
break;
|
|
411 |
case 0x40:
|
|
412 |
slavio_serial_reset_chn(&serial->chn[1]);
|
|
413 |
return;
|
|
414 |
case 0x80:
|
|
415 |
slavio_serial_reset_chn(&serial->chn[0]);
|
|
416 |
return;
|
|
417 |
case 0xc0:
|
|
418 |
slavio_serial_reset(serial);
|
|
419 |
return;
|
|
420 |
}
|
|
421 |
break;
|
|
422 |
default:
|
|
423 |
break;
|
|
424 |
}
|
|
425 |
if (s->reg == 0)
|
|
426 |
s->reg = newreg;
|
|
427 |
else
|
|
428 |
s->reg = 0;
|
|
429 |
break;
|
|
405 |
break;
|
|
406 |
case 9:
|
|
407 |
switch (val & 0xc0) {
|
|
408 |
case 0:
|
|
409 |
default:
|
|
410 |
break;
|
|
411 |
case 0x40:
|
|
412 |
slavio_serial_reset_chn(&serial->chn[1]);
|
|
413 |
return;
|
|
414 |
case 0x80:
|
|
415 |
slavio_serial_reset_chn(&serial->chn[0]);
|
|
416 |
return;
|
|
417 |
case 0xc0:
|
|
418 |
slavio_serial_reset(serial);
|
|
419 |
return;
|
|
420 |
}
|
|
421 |
break;
|
|
422 |
default:
|
|
423 |
break;
|
|
424 |
}
|
|
425 |
if (s->reg == 0)
|
|
426 |
s->reg = newreg;
|
|
427 |
else
|
|
428 |
s->reg = 0;
|
|
429 |
break;
|
|
430 | 430 |
case 1: |
431 |
SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
|
|
431 |
SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
|
|
432 | 432 |
s->tx = val; |
433 |
if (s->wregs[5] & 8) { // tx enabled
|
|
434 |
if (s->chr)
|
|
435 |
qemu_chr_write(s->chr, &s->tx, 1);
|
|
436 |
else if (s->type == kbd) {
|
|
437 |
handle_kbd_command(s, val);
|
|
438 |
}
|
|
439 |
}
|
|
433 |
if (s->wregs[5] & 8) { // tx enabled
|
|
434 |
if (s->chr)
|
|
435 |
qemu_chr_write(s->chr, &s->tx, 1);
|
|
436 |
else if (s->type == kbd) {
|
|
437 |
handle_kbd_command(s, val);
|
|
438 |
}
|
|
439 |
}
|
|
440 | 440 |
s->rregs[0] |= 4; // Tx buffer empty |
441 | 441 |
s->rregs[1] |= 1; // All sent |
442 | 442 |
set_txint(s); |
443 |
break;
|
|
443 |
break;
|
|
444 | 444 |
default: |
445 |
break;
|
|
445 |
break;
|
|
446 | 446 |
} |
447 | 447 |
} |
448 | 448 |
|
... | ... | |
459 | 459 |
s = &serial->chn[channel]; |
460 | 460 |
switch (saddr) { |
461 | 461 |
case 0: |
462 |
SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
|
|
463 |
ret = s->rregs[s->reg];
|
|
464 |
s->reg = 0;
|
|
465 |
return ret;
|
|
462 |
SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
|
|
463 |
ret = s->rregs[s->reg];
|
|
464 |
s->reg = 0;
|
|
465 |
return ret;
|
|
466 | 466 |
case 1: |
467 |
s->rregs[0] &= ~1;
|
|
467 |
s->rregs[0] &= ~1;
|
|
468 | 468 |
clr_rxint(s); |
469 |
if (s->type == kbd || s->type == mouse)
|
|
470 |
ret = get_queue(s);
|
|
471 |
else
|
|
472 |
ret = s->rx;
|
|
473 |
SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
|
|
474 |
return ret;
|
|
469 |
if (s->type == kbd || s->type == mouse)
|
|
470 |
ret = get_queue(s);
|
|
471 |
else
|
|
472 |
ret = s->rx;
|
|
473 |
SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
|
|
474 |
return ret;
|
|
475 | 475 |
default: |
476 |
break;
|
|
476 |
break;
|
|
477 | 477 |
} |
478 | 478 |
return 0; |
479 | 479 |
} |
... | ... | |
484 | 484 |
int ret; |
485 | 485 |
|
486 | 486 |
if (((s->wregs[3] & 1) == 0) // Rx not enabled |
487 |
|| ((s->rregs[0] & 1) == 1)) // char already available
|
|
488 |
ret = 0;
|
|
487 |
|| ((s->rregs[0] & 1) == 1)) // char already available
|
|
488 |
ret = 0;
|
|
489 | 489 |
else |
490 |
ret = 1;
|
|
490 |
ret = 1;
|
|
491 | 491 |
//SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret); |
492 | 492 |
return ret; |
493 | 493 |
} |
... | ... | |
584 | 584 |
|
585 | 585 |
ret = slavio_serial_load_chn(f, &s->chn[0], version_id); |
586 | 586 |
if (ret != 0) |
587 |
return ret;
|
|
587 |
return ret;
|
|
588 | 588 |
ret = slavio_serial_load_chn(f, &s->chn[1], version_id); |
589 | 589 |
return ret; |
590 | 590 |
|
... | ... | |
607 | 607 |
s->chn[1].chr = chr2; |
608 | 608 |
|
609 | 609 |
for (i = 0; i < 2; i++) { |
610 |
s->chn[i].irq = irq;
|
|
611 |
s->chn[i].chn = 1 - i;
|
|
612 |
s->chn[i].type = ser;
|
|
613 |
if (s->chn[i].chr) {
|
|
614 |
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
|
|
610 |
s->chn[i].irq = irq;
|
|
611 |
s->chn[i].chn = 1 - i;
|
|
612 |
s->chn[i].type = ser;
|
|
613 |
if (s->chn[i].chr) {
|
|
614 |
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
|
|
615 | 615 |
serial_receive1, serial_event, &s->chn[i]); |
616 |
}
|
|
616 |
}
|
|
617 | 617 |
} |
618 | 618 |
s->chn[0].otherchn = &s->chn[1]; |
619 | 619 |
s->chn[1].otherchn = &s->chn[0]; |
... | ... | |
698 | 698 |
switch (val) { |
699 | 699 |
case 1: // Reset, return type code |
700 | 700 |
clear_queue(s); |
701 |
put_queue(s, 0xff);
|
|
702 |
put_queue(s, 4); // Type 4
|
|
703 |
put_queue(s, 0x7f);
|
|
704 |
break;
|
|
701 |
put_queue(s, 0xff);
|
|
702 |
put_queue(s, 4); // Type 4
|
|
703 |
put_queue(s, 0x7f);
|
|
704 |
break;
|
|
705 | 705 |
case 0xe: // Set leds |
706 | 706 |
s->led_mode = 1; |
707 | 707 |
break; |
708 | 708 |
case 7: // Query layout |
709 | 709 |
case 0xf: |
710 | 710 |
clear_queue(s); |
711 |
put_queue(s, 0xfe);
|
|
712 |
put_queue(s, 0); // XXX, layout?
|
|
713 |
break;
|
|
711 |
put_queue(s, 0xfe);
|
|
712 |
put_queue(s, 0); // XXX, layout?
|
|
713 |
break;
|
|
714 | 714 |
default: |
715 |
break;
|
|
715 |
break;
|
|
716 | 716 |
} |
717 | 717 |
} |
718 | 718 |
|
... | ... | |
768 | 768 |
if (!s) |
769 | 769 |
return; |
770 | 770 |
for (i = 0; i < 2; i++) { |
771 |
s->chn[i].irq = irq;
|
|
772 |
s->chn[i].chn = 1 - i;
|
|
773 |
s->chn[i].chr = NULL;
|
|
771 |
s->chn[i].irq = irq;
|
|
772 |
s->chn[i].chn = 1 - i;
|
|
773 |
s->chn[i].chr = NULL;
|
|
774 | 774 |
} |
775 | 775 |
s->chn[0].otherchn = &s->chn[1]; |
776 | 776 |
s->chn[1].otherchn = &s->chn[0]; |
Also available in: Unified diff