diff --git a/src/86box.c b/src/86box.c index 52f626bd2..9eefa039e 100644 --- a/src/86box.c +++ b/src/86box.c @@ -675,7 +675,7 @@ pc_send_ca(uint16_t sc) void pc_send_cad(void) { - pc_send_ca(0xE053); + pc_send_ca(0x153); } diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 7c844ec15..59b08de59 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -103,7 +103,8 @@ typedef struct { uint8_t mem[0x100]; int last_irq, old_last_irq, - reset_delay; + reset_delay, + out_new, out_delayed; uint32_t flags; @@ -125,10 +126,13 @@ uint8_t keyboard_set3_all_break; uint8_t keyboard_mode = 0x42; -static uint8_t kbc_queue_pos, channel_queue_pos[3]; -static uint16_t kbc_queue[48]; +static uint8_t key_ctrl_queue[16]; +static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; +static uint8_t key_queue[16]; +static int key_queue_start = 0, key_queue_end = 0; +uint8_t mouse_queue[16]; +int mouse_queue_start = 0, mouse_queue_end = 0; static uint8_t kbd_last_scan_code; -static uint8_t channel_queue[3][16]; static void (*mouse_write)(uint8_t val, void *priv) = NULL; static void *mouse_p = NULL; static uint8_t sc_or = 0; @@ -617,88 +621,65 @@ set_scancode_map(atkbd_t *dev) } + static void kbc_queue_reset(uint8_t channel) { - channel_queue_pos[channel] = 0; - memset(channel_queue[channel], 0x00, 16); + if (channel == 2) { + mouse_queue_start = mouse_queue_end = 0; + memset(mouse_queue, 0x00, sizeof(mouse_queue)); + } else if (channel == 1) { + key_queue_start = key_queue_end = 0; + memset(key_queue, 0x00, sizeof(key_queue)); + } else { + key_ctrl_queue_start = key_ctrl_queue_end = 0; + memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); + } } static void kbc_queue_add(uint8_t val, uint8_t channel) { - if ((channel > 0x03) || (kbc_queue_pos >= 48)) - return; - kbd_log("ATkbc: kbc_queue[%02X] = %04X;\n", kbc_queue_pos, val | (channel << 8)); - kbc_queue[kbc_queue_pos] = val | (channel << 8); - kbc_queue_pos++; -} - - -static int -channel_queue_get(uint8_t channel) -{ - int i, ret; - - if (channel_queue_pos[channel] != 0) { - ret = channel_queue[channel][0]; - kbd_log("ATkbc: channel_queue_get(%i): ret = %02X;\n", (uint32_t) channel, (uint32_t) channel_queue[channel][0]); - for (i = 0; i < 15; i++) - channel_queue[channel][i] = channel_queue[channel][i + 1]; - channel_queue_pos[channel]--; - } else - ret = -1; - - return ret; + if (channel == 2) { + kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); + mouse_queue[mouse_queue_end] = val; + mouse_queue_end = (mouse_queue_end + 1) & 0xf; + } else if (channel == 1) { + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + key_queue[key_queue_end] = val; + key_queue_end = (key_queue_end + 1) & 0xf; + } else { + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + key_ctrl_queue[key_ctrl_queue_end] = val; + key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; + } } static void add_to_kbc_queue_front(atkbd_t *dev, uint8_t val) { + kbd_log("ATkbc: Adding %02X to front...\n", val); dev->wantirq = 0; - picint(0x0000); + if (dev->mem[0] & 0x01) + picint(2); dev->out = val; - dev->status |= STAT_OFULL; - dev->status &= ~STAT_IFULL; - dev->status &= ~STAT_MFULL; + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; dev->last_irq = 0x0000; } -static int -channel_queue_check(atkbd_t *dev, uint8_t channel) -{ - int val; - - if (channel >= 0x03) - return 0; - - if ((channel == 0x01) && (dev->mem[0] & 0x10)) - return 0; - if ((channel == 0x02) && (((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) || (dev->mem[0] & 0x20))) - return 0; - - val = channel_queue_get(channel); - if (val == -1) - return 0; - kbc_queue_add(val & 0xff, channel); - - return 1; -} - - static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (channel_queue_pos[1] >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (channel_queue_pos[1] >= 16)); + if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); return; } - kbd_log("ATkbc: channel_queue[1][channel_queue_pos[1]] = %02X;\n", (uint32_t) val); - channel_queue[1][channel_queue_pos[1]] = val; - channel_queue_pos[1]++; + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + key_queue[key_queue_end] = val; + key_queue_end = (key_queue_end + 1) & 0xf; kbd_last_scan_code = val; } @@ -723,7 +704,6 @@ add_data_kbd_direct(atkbd_t *dev, uint8_t val) send = val; add_data_kbd_queue(dev, 1, send); - channel_queue_check(dev, 0x01); } @@ -731,7 +711,6 @@ static void add_data_kbd_raw(atkbd_t *dev, uint8_t val) { add_data_kbd_queue(dev, 1, val); - channel_queue_check(dev, 0x01); } @@ -739,45 +718,57 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t irq_table[4] = { 0x0002, 0x0002, 0x1000, 0xffff }; - int i, channel; - uint16_t val, irq; +#ifdef ENABLE_KEYBOARD_AT_LOG + const uint8_t channels[4] = { 1, 2, 0, 0 }; +#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - kbd_log("ATkbc: dev->last_irq = %04X, kbc_queue_pos = %i\n", (uint32_t) dev->last_irq, (uint32_t) kbc_queue_pos); - if ((dev->last_irq == 0xffff) && (kbc_queue_pos > 0)) { - val = kbc_queue[0]; - kbd_log("ATkbc: Word from queue: %04X\n", (uint32_t) val); - channel = (val >> 8) & 0x03; - for (i = 0; i < 47; i++) - kbc_queue[i] = kbc_queue[i + 1]; - kbc_queue_pos = (kbc_queue_pos - 1) & 0xff; - irq = irq_table[channel]; - if (channel < 0x03) { - dev->wantirq = 0; - if ((channel == 0) || (dev->mem[0] & channel)) - picint(irq); - dev->out = val & 0xff; - dev->status |= STAT_OFULL; - dev->status &= ~STAT_IFULL; - if (channel == 0x02) - dev->status |= STAT_MFULL; - else - dev->status &= ~STAT_MFULL; - dev->last_irq = irq; + if (dev->out_new != -1 && !dev->last_irq) { + dev->wantirq = 0; + if (dev->out_new & 0x100) { + if (dev->mem[0] & 0x02) + picint(0x1000); + kbd_log("ATkbc: %02X coming from channel 2\n"); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; + dev->last_irq = 2; } } - for (i = 0x00; i < 0x03; i++) { - if (channel_queue_check(dev, i)) - break; + if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { + kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); + dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; + key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { + kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); + dev->out_new = dev->out_delayed; + dev->out_delayed = -1; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { + kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); + dev->out_new = mouse_queue[mouse_queue_start] | 0x100; + mouse_queue_start = (mouse_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { + kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); + dev->out_new = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; } - if (dev->reset_delay > 0) { + if (dev->reset_delay) { dev->reset_delay--; - if (dev->reset_delay == 0) + if (!dev->reset_delay) { + kbd_log("ATkbc: Sending AA on keyboard reset...\n"); add_data_kbd_direct(dev, 0xaa); + } } } @@ -787,10 +778,13 @@ add_data(atkbd_t *dev, uint8_t val) { kbd_log("ATkbc: add to queue\n"); - if (channel_queue_pos[0] < 16) { - kbd_log("ATkbc: channel_queue[0][channel_queue_pos[0]] = %02X;\n", (uint32_t) val); - channel_queue[0][channel_queue_pos[0]] = val; - channel_queue_pos[0]++; + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + key_ctrl_queue[key_ctrl_queue_end] = val; + key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; + + if (!(dev->out_new & 0x300)) { + dev->out_delayed = dev->out_new; + dev->out_new = -1; } } @@ -1112,6 +1106,7 @@ pulse_output(atkbd_t *dev, uint8_t mask) { if (mask != 0x0f) { dev->old_output_port = dev->output_port & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); write_output(dev, dev->output_port & (0xf0 | mask)); timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); } @@ -1123,6 +1118,7 @@ pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; + kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); write_output(dev, dev->output_port | dev->old_output_port); } @@ -1876,7 +1872,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xf6: /* set defaults */ kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); keyboard_scan = (val == 0xf6); - kbc_queue_reset(1); kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", val, keyboard_scan, dev->mem[0]); add_data_kbd_direct(dev, 0xfa); @@ -1994,13 +1989,12 @@ kbd_write(uint16_t port, uint8_t val, void *priv) if (! dev->initialized) { kbd_log("ATkbc: self-test reinitialization\n"); dev->initialized = 1; - memset(kbc_queue, 0x00, 48 * sizeof(uint16_t)); - kbc_queue_pos = 0; - for (i = 0; i < 2; i++) + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) kbc_queue_reset(i); kbd_last_scan_code = 0x00; dev->status &= ~STAT_OFULL; - dev->last_irq = 0xffff; + dev->last_irq = dev->old_last_irq = 0; } dev->status |= STAT_SYSFLAG; dev->mem[0] |= 0x04; @@ -2115,18 +2109,10 @@ kbd_read(uint16_t port, void *priv) switch (port) { case 0x60: - ret = dev->out; - dev->status &= ~(STAT_OFULL); - if ((dev->last_irq == 0x0002) || (dev->last_irq == 0x1000)) - picintc(dev->last_irq); - dev->last_irq = 0xffff; - if (dev->old_last_irq != 0xffff) { - dev->out = dev->old_out; - dev->last_irq = dev->old_last_irq; - dev->status = dev->old_status; - dev->old_last_irq = 0xffff; - picint(dev->last_irq); - } + ret = dev->out; + dev->status &= ~STAT_OFULL; + picintc(dev->last_irq); + dev->last_irq = 0; break; case 0x61: @@ -2228,8 +2214,7 @@ kbd_reset(void *priv) dev->mem[0] |= CCB_TRANSLATE; dev->wantirq = 0; write_output(dev, 0xcf); - dev->last_irq = 0xffff; - dev->old_last_irq = 0xffff; + dev->last_irq = dev->old_last_irq = 0; dev->secr_phase = 0; dev->key_wantdata = 0; @@ -2248,9 +2233,8 @@ kbd_reset(void *priv) set_enable_mouse(dev, 0); mouse_scan = 0; - memset(kbc_queue, 0x00, 48 * sizeof(uint16_t)); - kbc_queue_pos = 0; - for (i = 0; i < 2; i++) + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) kbc_queue_reset(i); kbd_last_scan_code = 0; @@ -2583,25 +2567,21 @@ keyboard_at_adddata_keyboard_raw(uint8_t val) void keyboard_at_adddata_mouse(uint8_t val) { - if (channel_queue_pos[2] >= 16) - return; - channel_queue[2][channel_queue_pos[2]] = val; - channel_queue_pos[2]++; + kbc_queue_add(val, 2); } void keyboard_at_mouse_reset(void) { - channel_queue_pos[2] = 0; - memset(channel_queue[2], 0x00, 16); + kbc_queue_reset(2); } uint8_t keyboard_at_mouse_pos(void) { - return channel_queue_pos[2]; + return ((mouse_queue_end - mouse_queue_start) & 0xf); }