This commit is contained in:
RichardG867
2023-04-08 21:39:27 -03:00
2 changed files with 172 additions and 70 deletions

View File

@@ -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"

View File

@@ -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