mirror of
https://github.com/86Box/86Box.git
synced 2026-02-28 09:54:21 -07:00
IBM 5550: Add machine config for test mode
* Added a machine config for the RNA test mode. * Changed the keyboard reset sequence to work on the RNA test correctly. * Reduced screen updates for text cursor.
This commit is contained in:
@@ -1522,7 +1522,7 @@ extern int machine_xt_compaq_deskpro_init(const machine_t *);
|
||||
|
||||
/* m_xt_ibm5550.c */
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t ibm5550_vid_device;
|
||||
extern const device_t ibm5550_device;
|
||||
#endif
|
||||
extern int machine_xt_ibm5550_init(const machine_t *);
|
||||
|
||||
|
||||
@@ -161,12 +161,12 @@ enum epoch_nvr_ADDR {
|
||||
};
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
//#define ENABLE_EPOCH_LOG 1
|
||||
// #define ENABLE_EPOCH_LOG 1
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EPOCH_LOG
|
||||
#define ENABLE_EPOCH_DEBUGIO 1
|
||||
// #define ENABLE_EPOCH_DEBUGKBD 1
|
||||
// #define ENABLE_EPOCH_DEBUGIO 1
|
||||
#define ENABLE_EPOCH_DEBUGKBD 1
|
||||
int epoch_do_log = ENABLE_EPOCH_LOG;
|
||||
|
||||
static void
|
||||
@@ -279,6 +279,8 @@ typedef struct epoch_t {
|
||||
nvr_t nvr;
|
||||
int nvrctrl;
|
||||
int nvrdata;
|
||||
|
||||
int testmode;
|
||||
|
||||
} epoch_t;
|
||||
|
||||
@@ -1154,7 +1156,7 @@ epoch_poll(void *priv)
|
||||
epoch->cursoron = 1;
|
||||
break;
|
||||
}
|
||||
if (!(epoch->blink & (0x08 - 2))) /* force redrawing for cursor and blink attribute */
|
||||
if (!(epoch->blink & (0x08 - 1))) /* force redrawing for cursor and blink attribute */
|
||||
epoch->fullchange = 3;
|
||||
}
|
||||
epoch->blink++;
|
||||
@@ -1429,15 +1431,21 @@ epoch_misc_in(uint16_t port, void *priv)
|
||||
/*
|
||||
I/O A0h R:
|
||||
xxxx xxx1: Memory or parity error?
|
||||
xxxx xx1x: Test switch (physical switch on the rear panel)
|
||||
x1xx xxxx: Sense DREQ? (only used in diag test)
|
||||
0xxx xxxx: Coprocessor installed?
|
||||
*/
|
||||
case 0xA0:
|
||||
if(!epoch->parityenabled)
|
||||
ret &= 0xfe;
|
||||
else
|
||||
ret = epoch->parityerror & 1;
|
||||
ret = 0;
|
||||
if (epoch->parityenabled)
|
||||
ret |= epoch->parityerror & 1;
|
||||
if (fpu_type == FPU_NONE)
|
||||
ret |= 0x80;
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (dma_get_drq(i))
|
||||
ret |= 0x40;
|
||||
if (epoch->testmode)
|
||||
ret |= 0x02;
|
||||
break;
|
||||
case 0xA1: /* High address where memory error occured */
|
||||
ret = epoch->parityerroraddr;
|
||||
@@ -1549,15 +1557,16 @@ x1xx xxxx: Enable parity update (Disable this -> Write data -> Enable this -> Re
|
||||
typedef struct epochkbd_t {
|
||||
int want_irq;
|
||||
int blocked;
|
||||
uint8_t irq_state;
|
||||
|
||||
uint8_t pa;
|
||||
uint8_t pb;
|
||||
uint8_t clk_hold;
|
||||
uint8_t key_waiting;
|
||||
uint8_t kbd_reset_step;
|
||||
uint8_t mouse_reset_step;
|
||||
int8_t kbd_readdata_step;
|
||||
int mouse_enabled;
|
||||
int mouse_queue_num;
|
||||
int kbc_resetstep;
|
||||
uint8_t mouse_queue[4];
|
||||
|
||||
pc_timer_t send_delay_timer;
|
||||
@@ -1572,22 +1581,33 @@ kbd_epoch_poll(void *priv)
|
||||
{
|
||||
epochkbd_t *kbd = (epochkbd_t *) priv;
|
||||
|
||||
timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC);
|
||||
timer_advance_u64(&kbd->send_delay_timer, 250 * TIMER_USEC);
|
||||
|
||||
if (kbd->pb & 0x04) /* controller is sending something to keyboard */
|
||||
return;
|
||||
|
||||
if (kbd->kbd_readdata_step < 16)
|
||||
kbd->kbd_readdata_step++;
|
||||
|
||||
if (!(kbd->pb & 0x08)) /* keyboard interrupt is disabled */
|
||||
return;
|
||||
|
||||
if (kbd->want_irq) {
|
||||
kbd->want_irq = 0;
|
||||
kbd->pa = kbd->key_waiting;
|
||||
kbd->blocked = 1;
|
||||
picint(EPOCH_IRQ3_BIT);
|
||||
epoch_kbdlog("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n");
|
||||
if (kbd->want_irq && kbd->kbd_readdata_step >= 16) {
|
||||
if (kbd->blocked) {
|
||||
kbd->want_irq = 0;
|
||||
kbd->irq_state = 1;
|
||||
picint(EPOCH_IRQ3_BIT);
|
||||
epoch_kbdlog("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n");
|
||||
} else {
|
||||
kbd->pa = kbd->key_waiting;
|
||||
kbd->kbd_readdata_step = -4;
|
||||
kbd->blocked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (kbd->irq_state && (kbd->pb & 0x01)) /* Trigger interrupt repeatedly (for RNA test) */
|
||||
picint(EPOCH_IRQ3_BIT);
|
||||
|
||||
if (!kbd->blocked) {
|
||||
if (kbd->mouse_queue_num > 0) {
|
||||
kbd->mouse_queue_num--;
|
||||
@@ -1641,6 +1661,21 @@ kbd_adddata_ex(uint16_t val)
|
||||
kbd_epoch_adddata_process(val, kbd_epoch_adddata);
|
||||
}
|
||||
|
||||
static void
|
||||
kbd_epoch_softreset(void *priv)
|
||||
{
|
||||
epochkbd_t *kbd = (epochkbd_t *) priv;
|
||||
key_queue_start = key_queue_end = 0;
|
||||
kbd->kbd_readdata_step = 16;
|
||||
kbd->want_irq = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd->clk_hold = 0;
|
||||
kbd->mouse_queue_num = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd->irq_state = 0;
|
||||
kbd->pa = 0;
|
||||
picintc(EPOCH_IRQ3_BIT);
|
||||
}
|
||||
/*
|
||||
I/O 61h W:
|
||||
xxxx xxx1: ? (used by kbd interrupt in DOS)
|
||||
@@ -1672,20 +1707,26 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
new_clock = !(val & 0x04);
|
||||
/* Trigger kbd reset after the clk line is reset to a high level */
|
||||
if (kbd->clk_hold && new_clock) {
|
||||
key_queue_start = key_queue_end = 0;
|
||||
kbd->want_irq = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd->kbd_reset_step = 0;
|
||||
kbd->clk_hold = 0;
|
||||
kbd->mouse_enabled = 0;
|
||||
kbd->mouse_queue_num = 0;
|
||||
kbd->mouse_enabled = 0;
|
||||
kbd_epoch_softreset(kbd);
|
||||
epoch_kbdlog("epochkbd: Starting keyboard reset sequence.\n");
|
||||
/* IBM 5556 keyboards send three bytes of identification code in the reset sequence.
|
||||
DOS K3.44 supports following IDs:
|
||||
A5xx1x: ? (standard layout)
|
||||
A6xx1x: AIUEO RPQ Keyboard
|
||||
B1xx1x, B2xx1x: Type 3, 4 Keyboard (1972 JIS layout)
|
||||
B5xx1x: ? (standard layout)
|
||||
*/
|
||||
kbd_epoch_adddata(0xA5);
|
||||
kbd_epoch_adddata(0x00);
|
||||
kbd_epoch_adddata(0x10);
|
||||
}
|
||||
} else if ((val & 0x18) == 0x18) {
|
||||
new_clock = !(val & 0x04);
|
||||
if (kbd->clk_hold && new_clock) {
|
||||
kbd->mouse_reset_step = 0;
|
||||
kbd_epoch_softreset(kbd);
|
||||
epoch_kbdlog("epochkbd: Starting mouse reset sequence.\n");
|
||||
kbd_epoch_adddata(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1706,8 +1747,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
|
||||
/* clear buffer */
|
||||
kbd->pa = 0;
|
||||
kbd->blocked = 0;
|
||||
/* IRQ will be cleared by the software */
|
||||
// picintc(EPOCH_IRQ3_BIT);
|
||||
kbd->irq_state = 0;
|
||||
picintc(EPOCH_IRQ3_BIT);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1736,35 +1777,29 @@ kbd_read(uint16_t port, void *priv)
|
||||
case 0x61: /* Keyboard Control Register (aka Port B) */
|
||||
ret = kbd->pb & 0xf0; /* reset sense bit */
|
||||
ret |= 0x0c; /* reset sense bit */
|
||||
if (kbd->kbd_reset_step < 18) {
|
||||
if (kbd->kbd_readdata_step < 16) {
|
||||
ret &= 0xf3;
|
||||
if (!!(kbd->kbd_reset_step & 1))
|
||||
ret |= 0x04;
|
||||
switch (kbd->kbd_reset_step >> 1) { /* AAh (0 1010 1010) in serial data */
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
ret |= 0x08;
|
||||
switch (kbd->kbd_readdata_step) {
|
||||
case -4:
|
||||
ret |= 0x0c; /* start bit */
|
||||
break;
|
||||
case -3:
|
||||
ret |= 0x0c; /* start bit */
|
||||
break;
|
||||
case -2:
|
||||
ret |= 0x08; /* start bit */
|
||||
break;
|
||||
case -1:
|
||||
ret |= 0x0c; /* start bit */
|
||||
break;
|
||||
default:
|
||||
ret |= 0x00;
|
||||
if (!!(kbd->kbd_readdata_step & 1))
|
||||
ret |= 0x04;
|
||||
if ((kbd->key_waiting >> (kbd->kbd_readdata_step >> 1)) & 1)
|
||||
ret |= 0x08;
|
||||
break;
|
||||
}
|
||||
epoch_kbdlog(" reset step: %d %x %x", kbd->kbd_reset_step, ret & 0x08, ret & 0x04);
|
||||
epoch_kbdlog(" Clk: %x %x\n", kbd->blocked, kbd->clk_hold);
|
||||
kbd->kbd_reset_step++;
|
||||
/* Specific 5556 keyboards send three bytes of identification code,
|
||||
but this simply sends AAh that can pass the IPL and DOS K3.4 init. */
|
||||
if (kbd->kbd_reset_step == 18)
|
||||
kbd_epoch_adddata(0xaa);
|
||||
} else if (kbd->mouse_reset_step < 20) {
|
||||
ret &= 0xf3;
|
||||
if (!!(kbd->mouse_reset_step & 1))
|
||||
ret |= 0x04;
|
||||
epoch_kbdlog(" reset step: %d %x %x\n", kbd->mouse_reset_step, ret & 0x08, ret & 0x04);
|
||||
kbd->mouse_reset_step++;
|
||||
epoch_kbdlog(" rdata step: %d %x %x\n", kbd->kbd_readdata_step, ret & 0x08, ret & 0x04);
|
||||
}
|
||||
|
||||
/* Bit 1: Timer 2 (Speaker) out state */
|
||||
@@ -1777,7 +1812,8 @@ kbd_read(uint16_t port, void *priv)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
epoch_kbdlog("%04X:%04X epochkbd: Port %02X in : %02X pb: %02x CX: %04x\n", cs >> 4, cpu_state.pc, port, ret, kbd->pb, CX);
|
||||
// if (port != 0x61)
|
||||
epoch_kbdlog("%04X:%04X epochkbd: Port %02X in : %02X pb: %02x CX: %04x\n", cs >> 4, cpu_state.pc, port, ret, kbd->pb, CX);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1786,21 +1822,11 @@ kbd_reset(void *priv)
|
||||
{
|
||||
epochkbd_t *kbd = (epochkbd_t *) priv;
|
||||
|
||||
kbd->want_irq = 0;
|
||||
kbd->blocked = 0;
|
||||
kbd->pa = 0x00;
|
||||
kbd->pb = 0x00;
|
||||
kbd->kbd_reset_step = 0xff;
|
||||
kbd->mouse_reset_step = 0xff;
|
||||
|
||||
keyboard_scan = 1;
|
||||
|
||||
key_queue_start = 0;
|
||||
key_queue_end = 0;
|
||||
kbd_epoch_softreset(kbd);
|
||||
kbd->pb = 0x00;
|
||||
|
||||
keyboard_scan = 1;
|
||||
kbd->mouse_enabled = 0;
|
||||
kbd->mouse_queue_num = 0;
|
||||
kbd_epoch_adddata(0xaa);
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -1843,7 +1869,7 @@ kbd_close(void *priv)
|
||||
}
|
||||
|
||||
static const device_t kbc_epoch_device = {
|
||||
.name = "IBM 5550 Keyboard Controller",
|
||||
.name = "IBM 5556 Keyboard and Mouse",
|
||||
.internal_name = "kbc_epoch",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
@@ -2196,6 +2222,7 @@ epoch_init(UNUSED(const device_t *info))
|
||||
{
|
||||
epoch_t *epoch = calloc(1, sizeof(epoch_t));
|
||||
epoch->font24 = device_get_config_int("model");
|
||||
epoch->testmode = device_get_config_int("testmode");
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_NONE, &timing_epoch_vid);
|
||||
video_update_timing();
|
||||
@@ -2233,7 +2260,7 @@ epoch_init(UNUSED(const device_t *info))
|
||||
|
||||
io_sethandler(0x44, 0x0001,
|
||||
epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch);
|
||||
io_sethandler(0xA0, 0x0006,
|
||||
io_sethandler(0xA0, 0x0008,
|
||||
epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch);
|
||||
io_sethandler(0x310, 0x0008,
|
||||
epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch);
|
||||
@@ -2342,13 +2369,20 @@ static const device_config_t epoch_config[] = {
|
||||
{ .description = "" }
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "testmode",
|
||||
.description = "Test mode",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_int = 0,
|
||||
.selection = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
const device_t ibm5550_vid_device = {
|
||||
.name = "IBM 5550 Video Adapter",
|
||||
.internal_name = "ibm5550vid",
|
||||
const device_t ibm5550_device = {
|
||||
.name = "IBM 5551 System Unit",
|
||||
.internal_name = "ibm5550",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = epoch_init,
|
||||
@@ -2418,7 +2452,7 @@ machine_xt_ibm5550_init(const machine_t *model)
|
||||
pit_ibm5550_init();
|
||||
nmi_mask = 0;
|
||||
|
||||
device_add(&ibm5550_vid_device);
|
||||
device_add(&ibm5550_device);
|
||||
|
||||
device_add(&lpt_port_device);
|
||||
serial_t *uart = device_add(&ns8250_device);
|
||||
@@ -2428,6 +2462,9 @@ machine_xt_ibm5550_init(const machine_t *model)
|
||||
/* Tell mouse driver about our internal mouse. */
|
||||
mouse_reset();
|
||||
mouse_set_buttons(2);
|
||||
/* I don't know the actual polling speed, but
|
||||
a higher value may cause a conflict with the mouse driver */
|
||||
mouse_set_sample_rate(30.0);
|
||||
mouse_set_poll(epoch_mouse_poll, kbc);
|
||||
}
|
||||
|
||||
|
||||
@@ -2724,11 +2724,11 @@ const machine_t machines[] = {
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = NULL,
|
||||
.device = &ibm5550_device,
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &ibm5550_vid_device,
|
||||
.vid_device = NULL,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user