From 4471849891061afd3765affeeed41637c1e0f3e6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 9 Apr 2023 00:59:10 +0200 Subject: [PATCH 1/2] The keyboard now is now also a state machine. --- src/device/keyboard_at.c | 239 +++++++++++++++++++++++++++------------ 1 file changed, 169 insertions(+), 70 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index e440b3b07..b94343250 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -93,7 +93,10 @@ enum { KBC_STATE_RESET = 0, - KBC_STATE_NORMAL, + KBC_STATE_MAIN_IBF, + KBC_STATE_MAIN_KBD, + KBC_STATE_MAIN_MOUSE, + KBC_STATE_MAIN_BOTH, KBC_STATE_KBC_OUT, KBC_STATE_KBC_PARAM, KBC_STATE_KBD, @@ -102,6 +105,18 @@ enum { #define KBC_STATE_SCAN_KBD KBC_STATE_KBD #define KBC_STATE_SCAN_MOUSE KBC_STATE_MOUSE +enum { + DEV_STATE_RESET = 0, + DEV_STATE_MAIN_1, + DEV_STATE_MAIN_2, + DEV_STATE_MAIN_CMD, + DEV_STATE_MAIN_OUT, + DEV_STATE_MAIN_WANT_IN, + DEV_STATE_MAIN_IN, + DEV_STATE_MAIN_WANT_RESET, + DEV_STATE_RESET_OUT +}; + typedef struct { uint8_t command, status, ib, out, old_out, secr_phase, mem_addr, input_port, @@ -702,7 +717,7 @@ kbc_irq(atkbd_t *dev, uint16_t irq, int raise) { picint_common(irq, (dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF, raise); if (raise) - dev->irq_levels |= irq; + dev->irq_levels = irq; else dev->irq_levels &= ~irq; } @@ -814,7 +829,7 @@ kbc_ibf_process(atkbd_t *dev) { /* IBF set, process both commands and data. */ dev->status &= ~STAT_IFULL; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; if (dev->status & STAT_CD) kbc_process_cmd(dev); else { @@ -836,7 +851,7 @@ kbc_scan_kbd_at(atkbd_t *dev) if (dev->out_new != -1) { add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); dev->out_new = -1; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; } else if (dev->status & STAT_IFULL) kbc_ibf_process(dev); /* AT mode. */ @@ -858,9 +873,8 @@ kbc_scan_kbd_at(atkbd_t *dev) } else add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); dev->out_new = -1; - dev->kbc_state = KBC_STATE_NORMAL; - } else if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; + } } } } @@ -876,7 +890,9 @@ kbc_poll_at(atkbd_t *dev) kbc_process_cmd(dev); } break; - case KBC_STATE_NORMAL: + case KBC_STATE_MAIN_IBF: + case KBC_STATE_MAIN_MOUSE: + case KBC_STATE_SCAN_MOUSE: if (dev->status & STAT_OFULL) { /* OBF set, wait until it is cleared but still process commands. */ if ((dev->status & STAT_IFULL) && (dev->status & STAT_CD)) { @@ -885,23 +901,28 @@ kbc_poll_at(atkbd_t *dev) } } else if (dev->status & STAT_IFULL) kbc_ibf_process(dev); - else - kbc_scan_kbd_at(dev); + else if (!(dev->mem[0x20] & 0x10)) + dev->kbc_state = KBC_STATE_MAIN_KBD; + break; + case KBC_STATE_MAIN_KBD: + case KBC_STATE_MAIN_BOTH: + (void) kbc_scan_kbd_at(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; break; case KBC_STATE_KBC_OUT: /* Keyboard controller command want to output multiple bytes. */ if (dev->status & STAT_IFULL) { /* Data from host aborts dumping. */ - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; kbc_ibf_process(dev); } /* Do not continue dumping until OBF is clear. */ if (!(dev->status & STAT_OFULL)) { - kbd_log("ATkbc: %02X coming from channel 0\n", dev->out_new & 0xff); + kbd_log("ATkbc: %02X coming from channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); add_to_kbc_queue_front(dev, key_ctrl_queue[key_ctrl_queue_start], 0, 0x00); key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0x3f; if (key_ctrl_queue_start == key_ctrl_queue_end) - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; } break; case KBC_STATE_KBC_PARAM: @@ -909,7 +930,7 @@ kbc_poll_at(atkbd_t *dev) if (dev->status & STAT_IFULL) { /* Command written, abort current command. */ if (dev->status & STAT_CD) - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; dev->status &= ~STAT_IFULL; kbc_process_cmd(dev); @@ -921,13 +942,23 @@ kbc_poll_at(atkbd_t *dev) } } +/* + Correct Procedure: + 1. Controller asks the device (keyboard or mouse) for a byte. + 2. The device, unless it's in the reset or command states, sees if there's anything to give it, + and if yes, begins the transfer. + 3. The controller checks if there is a transfer, if yes, transfers the byte and sends it to the host, + otherwise, checks the next device, or if there is no device left to check, checks if IBF is full + and if yes, processes it. + */ static int kbc_scan_kbd_ps2(atkbd_t *dev) { if (dev->out_new != -1) { + kbd_log("ATkbc: %02X coming from channel 1\n", dev->out_new & 0xff); add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); dev->out_new = -1; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; return 1; } @@ -938,9 +969,10 @@ static int kbc_scan_aux_ps2(atkbd_t *dev) { if (dev->out_new_mouse != -1) { + kbd_log("ATkbc: %02X coming from channel 2\n", dev->out_new_mouse & 0xff); add_to_kbc_queue_front(dev, dev->out_new_mouse, 2, 0x00); dev->out_new_mouse = -1; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; return 1; } @@ -952,50 +984,57 @@ kbc_poll_ps2(atkbd_t *dev) { switch (dev->kbc_state) { case KBC_STATE_RESET: + // pclog("KBC_STATE_RESET\n"); if (dev->status & STAT_IFULL) { dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) kbc_process_cmd(dev); } break; - case KBC_STATE_NORMAL: + case KBC_STATE_MAIN_IBF: + // pclog("KBC_STATE_MAIN_IBF\n"); if (dev->status & STAT_IFULL) kbc_ibf_process(dev); else if (!(dev->status & STAT_OFULL)) { if (dev->mem[0x20] & 0x20) { if (!(dev->mem[0x20] & 0x10)) { dev->output_port &= 0xbf; - - if (kbc_scan_kbd_ps2(dev) == 0) { - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - } + dev->kbc_state = KBC_STATE_MAIN_KBD; } } else { dev->output_port &= 0xf7; - if (dev->mem[0x20] & 0x10) { - if (kbc_scan_aux_ps2(dev) == 0) { - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - } - } else { + if (dev->mem[0x20] & 0x10) + dev->kbc_state = KBC_STATE_MAIN_MOUSE; + else { dev->output_port &= 0xbf; - - if (kbc_scan_kbd_ps2(dev) == 0) { - if (kbc_scan_aux_ps2(dev) == 0) { - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - } - } + dev->kbc_state = KBC_STATE_MAIN_BOTH; } } } break; + case KBC_STATE_MAIN_KBD: + // pclog("KBC_STATE_MAIN_KBD\n"); + (void) kbc_scan_kbd_ps2(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; + break; + case KBC_STATE_MAIN_MOUSE: + // pclog("KBC_STATE_MAIN_MOUSE\n"); + (void) kbc_scan_aux_ps2(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; + break; + case KBC_STATE_MAIN_BOTH: + // pclog("KBC_STATE_MAIN_BOTH\n"); + if (kbc_scan_kbd_ps2(dev)) + dev->kbc_state = KBC_STATE_MAIN_IBF; + else + dev->kbc_state = KBC_STATE_MAIN_MOUSE; + break; case KBC_STATE_KBC_OUT: + // pclog("KBC_STATE_KBC_OUT\n"); /* Keyboard controller command want to output multiple bytes. */ if (dev->status & STAT_IFULL) { /* Data from host aborts dumping. */ - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; kbc_ibf_process(dev); } /* Do not continue dumping until OBF is clear. */ @@ -1004,29 +1043,104 @@ kbc_poll_ps2(atkbd_t *dev) add_to_kbc_queue_front(dev, key_ctrl_queue[key_ctrl_queue_start], 0, 0x00); key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0x3f; if (key_ctrl_queue_start == key_ctrl_queue_end) - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; } break; case KBC_STATE_KBC_PARAM: + // pclog("KBC_STATE_KBC_PARAM\n"); /* Keyboard controller command wants data, wait for said data. */ if (dev->status & STAT_IFULL) { /* Command written, abort current command. */ if (dev->status & STAT_CD) - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; dev->status &= ~STAT_IFULL; kbc_process_cmd(dev); } break; case KBC_STATE_SCAN_KBD: + // pclog("KBC_STATE_SCAN_KBD\n"); (void) kbc_scan_kbd_ps2(dev); break; case KBC_STATE_SCAN_MOUSE: + // pclog("KBC_STATE_SCAN_MOUSE\n"); (void) kbc_scan_aux_ps2(dev); break; } } +static void +kbc_poll_kbd(atkbd_t *dev) +{ + switch (dev->kbd_state) { + case DEV_STATE_RESET: + /* Reset state. */ + if (dev->reset_delay) { + dev->reset_delay--; + if (!dev->reset_delay) { + kbd_log("ATkbc: Sending AA on keyboard reset...\n"); + add_data_kbd_front(dev, 0xaa); + dev->kbd_state = DEV_STATE_RESET_OUT; + } + } + break; + case DEV_STATE_MAIN_1: + /* Process the command if needed and then return to main loop #2. */ + if (dev->key_wantcmd) { + kbd_log("ATkbc: Processing keyboard command...\n"); + kbd_process_cmd(dev); + dev->key_wantcmd = 0; + } else + dev->kbd_state = DEV_STATE_MAIN_2; + break; + case DEV_STATE_MAIN_2: + /* Output from scan queue if needed and then return to main loop #1. */ + if (keyboard_scan && (key_queue_start != key_queue_end)) { + kbd_log("ATkbc: %02X (DATA) 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; + } + dev->kbd_state = DEV_STATE_MAIN_1; + break; + case DEV_STATE_MAIN_OUT: + case DEV_STATE_RESET_OUT: + /* Output command resposne and then return to main loop #2. */ + if (key_cmd_queue_start != key_cmd_queue_end) { + kbd_log("ATkbc: %02X (CMD ) on channel 1\n", key_cmd_queue[key_cmd_queue_start]); + dev->out_new = key_cmd_queue[key_cmd_queue_start]; + key_cmd_queue_start = (key_cmd_queue_start + 1) & 0xf; + } + dev->kbd_state = (dev->kbd_state == DEV_STATE_RESET_OUT) ? DEV_STATE_MAIN_1 : DEV_STATE_MAIN_2; + break; + case DEV_STATE_MAIN_WANT_IN: + /* Output command response and then wait for host data. */ + if (key_cmd_queue_start != key_cmd_queue_end) { + kbd_log("ATkbc: %02X (CMD ) on channel 1\n", key_cmd_queue[key_cmd_queue_start]); + dev->out_new = key_cmd_queue[key_cmd_queue_start]; + key_cmd_queue_start = (key_cmd_queue_start + 1) & 0xf; + } + dev->kbd_state = DEV_STATE_MAIN_IN; + break; + case DEV_STATE_MAIN_IN: + /* Wait for host data. */ + if (dev->key_wantcmd) { + kbd_log("ATkbc: Processing keyboard command...\n"); + kbd_process_cmd(dev); + dev->key_wantcmd = 0; + } + break; + case DEV_STATE_MAIN_WANT_RESET: + /* Output command response and then go to the reset state. */ + if (key_cmd_queue_start != key_cmd_queue_end) { + kbd_log("ATkbc: %02X (CMD ) on channel 1\n", key_cmd_queue[key_cmd_queue_start]); + dev->out_new = key_cmd_queue[key_cmd_queue_start]; + key_cmd_queue_start = (key_cmd_queue_start + 1) & 0xf; + } + dev->kbd_state = DEV_STATE_RESET; + break; + } +} + /* TODO: State machines for controller, keyboard, and mouse. */ static void kbd_poll(void *priv) @@ -1042,31 +1156,7 @@ kbd_poll(void *priv) else kbc_poll_ps2(dev); - if (dev->reset_delay) { - dev->reset_delay--; - if (!dev->reset_delay) { - kbd_log("ATkbc: Sending AA on keyboard reset...\n"); - add_data_kbd_front(dev, 0xaa); - } - } else if (dev->key_wantcmd) { - if ((key_cmd_queue_start == key_cmd_queue_end) && (dev->out_new == -1) && (dev->reset_delay == 0)) { - kbd_log("ATkbc: Processing keyboard command...\n"); - kbd_process_cmd(dev); - dev->key_wantcmd = 0; - } - return; - } - if (dev->out_new == -1) { - if (key_cmd_queue_start != key_cmd_queue_end) { - kbd_log("ATkbc: %02X (CMD ) on channel 1\n", key_cmd_queue[key_cmd_queue_start]); - dev->out_new = key_cmd_queue[key_cmd_queue_start]; - key_cmd_queue_start = (key_cmd_queue_start + 1) & 0xf; - } else if (key_queue_start != key_queue_end) { - kbd_log("ATkbc: %02X (DATA) 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; - } - } + kbc_poll_kbd(dev); if (dev->mouse_reset_delay) { dev->mouse_reset_delay--; @@ -1082,8 +1172,7 @@ kbd_poll(void *priv) // dev->mouse_reset_delay = RESET_DELAY_TIME; dev->mouse_wantcmd = 0; } - } - if (dev->out_new_mouse == -1) { + } else if (dev->out_new_mouse == -1) { if (mouse_cmd_queue_start != mouse_cmd_queue_end) { kbd_log("ATkbc: %02X (CMD ) on channel 2\n", mouse_cmd_queue[mouse_cmd_queue_start]); dev->out_new_mouse = mouse_cmd_queue[mouse_cmd_queue_start]; @@ -2085,6 +2174,11 @@ kbd_key_reset(atkbd_t *dev, int do_fa) keyboard_scan = 1; dev->reset_delay = RESET_DELAY_TIME; + + if (do_fa) + dev->kbd_state = DEV_STATE_MAIN_WANT_RESET; + else + dev->kbd_state = DEV_STATE_RESET; } static void @@ -2095,6 +2189,8 @@ kbd_process_cmd(void *priv) /* Write data to keyboard. */ dev->mem[0x20] &= ~0x10; + dev->kbd_state = DEV_STATE_MAIN_OUT; + if (dev->key_wantdata) { dev->key_wantdata = 0; @@ -2159,6 +2255,7 @@ kbd_process_cmd(void *priv) add_data_kbd_raw(dev, 0xfa); dev->key_wantdata = 1; + dev->kbd_state = DEV_STATE_MAIN_WANT_IN; break; case 0xee: /* diagnostic echo */ @@ -2174,6 +2271,7 @@ kbd_process_cmd(void *priv) kbd_log("ATkbd: scan code set\n"); add_data_kbd_raw(dev, 0xfa); dev->key_wantdata = 1; + dev->kbd_state = DEV_STATE_MAIN_WANT_IN; break; case 0xf2: /* read ID */ @@ -2190,6 +2288,7 @@ kbd_process_cmd(void *priv) kbd_log("ATkbd: set typematic rate/delay\n"); add_data_kbd_raw(dev, 0xfa); dev->key_wantdata = 1; + dev->kbd_state = DEV_STATE_MAIN_WANT_IN; break; case 0xf4: /* enable keyboard */ @@ -2270,7 +2369,7 @@ kbc_process_cmd(void *priv) if (dev->status & STAT_CD) { /* Controller command. */ dev->want60 = 0; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; /* Clear the keyboard controller queue. */ kbc_queue_reset(0); @@ -2328,7 +2427,7 @@ kbc_process_cmd(void *priv) } kbc_queue_reset(0); - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; add_to_kbc_queue_front(dev, 0x55, 0, 0x00); break; @@ -2433,7 +2532,7 @@ kbc_process_cmd(void *priv) } else if (dev->want60) { /* Write data to controller. */ dev->want60 = 0; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; switch (dev->command) { case 0x60 ... 0x7f: @@ -2529,7 +2628,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } write_output(dev, val | 0x01); dev->want60 = 0; - dev->kbc_state = KBC_STATE_NORMAL; + dev->kbc_state = KBC_STATE_MAIN_IBF; return; } break; @@ -2644,7 +2743,7 @@ kbd_reset(void *priv) dev->kbc_state = KBC_STATE_RESET; /* Reset the keyboard. */ - // kbd_key_reset(dev, 0); + kbd_key_reset(dev, 0); } /* Reset the AT keyboard - this is needed for the PCI TRC and is done From 68e49b75bcf8c7d21961a16bc74e64501aa3cc45 Mon Sep 17 00:00:00 2001 From: richardg867 Date: Sat, 8 Apr 2023 20:30:07 -0300 Subject: [PATCH 2/2] Jenkins: Clean pacman cache after update --- .ci/build.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.ci/build.sh b/.ci/build.sh index a61cdc7f9..fc7290f4a 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -316,6 +316,9 @@ then pacman -S --needed --noconfirm "$pkg" done fi + + # Clean pacman cache when running under Jenkins to save disk space. + [ "$CI" = "true" ] && rm -rf /var/cache/pacman/pkg # Generate a new freetype DLL for this architecture. rm -f "$freetype_dll"