Reverted the AT keyboard code queues to before I created that mess, and fixed the DEL scan code sent on CTRL+ALT+DEL.

This commit is contained in:
OBattler
2021-04-26 06:24:27 +02:00
parent b4abc13e3c
commit 87b677b8a4
2 changed files with 105 additions and 125 deletions

View File

@@ -675,7 +675,7 @@ pc_send_ca(uint16_t sc)
void
pc_send_cad(void)
{
pc_send_ca(0xE053);
pc_send_ca(0x153);
}

View File

@@ -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);
}