Add timeout for kbc and pmc writes

This commit is contained in:
Jeremy Soller 2019-11-08 13:40:10 -07:00
parent 4269b25ecf
commit 1f87adb1fc
No known key found for this signature in database
GPG Key ID: E988B49EE78A7FB1
7 changed files with 61 additions and 36 deletions

View File

@ -6,7 +6,7 @@
#include <ec/kbc.h> #include <ec/kbc.h>
void kbc_init(void); void kbc_init(void);
void kbc_key(struct Kbc * kbc, uint16_t key, bool pressed); bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed);
void kbc_event(struct Kbc * kbc); void kbc_event(struct Kbc * kbc);
#endif // _BOARD_KBC_H #endif // _BOARD_KBC_H

View File

@ -10,20 +10,22 @@ void kbc_init(void) {
*(KBC.control) = 0; *(KBC.control) = 0;
} }
#define KBC_TIMEOUT 1000
// System flag // System flag
static bool kbc_system = false; static bool kbc_system = false;
// Translate from scancode set 2 to scancode set 1 // Translate from scancode set 2 to scancode set 1
// for basically no good reason // for basically no good reason
static bool kbc_translate = true; static bool kbc_translate = true;
void kbc_key(struct Kbc * kbc, uint16_t key, bool pressed) { bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) {
if (kbc_translate) { if (kbc_translate) {
key = keymap_translate(key); key = keymap_translate(key);
} }
switch (key & 0xFF00) { switch (key & 0xFF00) {
case K_E0: case K_E0:
printf(" E0\n"); printf(" E0\n");
kbc_keyboard(kbc, 0xE0); if (!kbc_keyboard(kbc, 0xE0, KBC_TIMEOUT)) return false;
key &= 0xFF; key &= 0xFF;
// Fall through // Fall through
case 0x00: case 0x00:
@ -32,13 +34,14 @@ void kbc_key(struct Kbc * kbc, uint16_t key, bool pressed) {
key |= 0x80; key |= 0x80;
} else { } else {
printf(" F0\n"); printf(" F0\n");
kbc_keyboard(kbc, 0xF0); if (!kbc_keyboard(kbc, 0xF0, KBC_TIMEOUT)) return false;
} }
} }
printf(" %02X\n", key); printf(" %02X\n", key);
kbc_keyboard(kbc, (uint8_t)key); if (!kbc_keyboard(kbc, (uint8_t)key, KBC_TIMEOUT)) return false;
break; break;
} }
return true;
} }
enum KbcState { enum KbcState {
@ -84,12 +87,12 @@ void kbc_event(struct Kbc * kbc) {
case 0xAA: case 0xAA:
printf(" test controller\n"); printf(" test controller\n");
// Why not pass the test? // Why not pass the test?
kbc_keyboard(kbc, 0x55); kbc_keyboard(kbc, 0x55, KBC_TIMEOUT);
break; break;
case 0xAB: case 0xAB:
printf(" test first port\n"); printf(" test first port\n");
// We _ARE_ the keyboard, so everything is good. // We _ARE_ the keyboard, so everything is good.
kbc_keyboard(kbc, 0x00); kbc_keyboard(kbc, 0x00, KBC_TIMEOUT);
break; break;
case 0xAD: case 0xAD:
printf(" disable first port\n"); printf(" disable first port\n");
@ -112,33 +115,34 @@ void kbc_event(struct Kbc * kbc) {
case 0xED: case 0xED:
printf(" set leds\n"); printf(" set leds\n");
state = KBC_STATE_SET_LEDS; state = KBC_STATE_SET_LEDS;
kbc_keyboard(kbc, 0xFA); kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break; break;
case 0xEE: case 0xEE:
printf(" echo\n"); printf(" echo\n");
// Hey, this is easy. I like easy commands // Hey, this is easy. I like easy commands
kbc_keyboard(kbc, 0xEE); kbc_keyboard(kbc, 0xEE, KBC_TIMEOUT);
break; break;
case 0xF0: case 0xF0:
printf(" get/set scancode\n"); printf(" get/set scancode\n");
state = KBC_STATE_SCANCODE; state = KBC_STATE_SCANCODE;
kbc_keyboard(kbc, 0xFA); kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break; break;
case 0xF4: case 0xF4:
printf(" enable scanning\n"); printf(" enable scanning\n");
kbscan_enabled = true; kbscan_enabled = true;
kbc_keyboard(kbc, 0xFA); kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break; break;
case 0xF5: case 0xF5:
printf(" disable scanning\n"); printf(" disable scanning\n");
kbscan_enabled = false; kbscan_enabled = false;
kbc_keyboard(kbc, 0xFA); kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break; break;
case 0xFF: case 0xFF:
printf(" self test\n"); printf(" self test\n");
kbc_keyboard(kbc, 0xFA); if (kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT)) {
// Yep, everything is still good, I promise // Yep, everything is still good, I promise
kbc_keyboard(kbc, 0xAA); kbc_keyboard(kbc, 0xAA, KBC_TIMEOUT);
}
break; break;
} }
break; break;
@ -171,7 +175,7 @@ void kbc_event(struct Kbc * kbc) {
case KBC_STATE_SET_LEDS: case KBC_STATE_SET_LEDS:
printf(" set leds\n"); printf(" set leds\n");
state = KBC_STATE_NORMAL; state = KBC_STATE_NORMAL;
kbc_keyboard(kbc, 0xFA); kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break; break;
case KBC_STATE_SCANCODE: case KBC_STATE_SCANCODE:
printf(" get/set scancode\n"); printf(" get/set scancode\n");
@ -181,7 +185,7 @@ void kbc_event(struct Kbc * kbc) {
printf(" set scancode set 2\n"); printf(" set scancode set 2\n");
break; break;
} }
kbc_keyboard(kbc, 0xFA); kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break; break;
case KBC_STATE_WRITE_PORT: case KBC_STATE_WRITE_PORT:
printf(" write port byte\n"); printf(" write port byte\n");

View File

@ -51,7 +51,7 @@ void kbscan_event(void) {
uint16_t key = keymap(i, j, kbscan_layer); uint16_t key = keymap(i, j, kbscan_layer);
printf("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b); printf("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b);
if (kbscan_enabled && key) { if (kbscan_enabled && key) {
kbc_key(&KBC, key, new_b); kbc_scancode(&KBC, key, new_b);
} }
} }
} }

View File

@ -1,6 +1,7 @@
#ifndef _EC_KBC_H #ifndef _EC_KBC_H
#define _EC_KBC_H #define _EC_KBC_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
void kbc_init(void); void kbc_init(void);
@ -28,8 +29,8 @@ extern struct Kbc __code KBC;
uint8_t kbc_status(struct Kbc * kbc); uint8_t kbc_status(struct Kbc * kbc);
uint8_t kbc_read(struct Kbc * kbc); uint8_t kbc_read(struct Kbc * kbc);
void kbc_keyboard(struct Kbc * kbc, uint8_t data); bool kbc_keyboard(struct Kbc * kbc, uint8_t data, int timeout);
void kbc_mouse(struct Kbc * kbc, uint8_t data); bool kbc_mouse(struct Kbc * kbc, uint8_t data, int timeout);
volatile uint8_t __xdata __at(0x1300) KBHICR; volatile uint8_t __xdata __at(0x1300) KBHICR;
volatile uint8_t __xdata __at(0x1302) KBIRQR; volatile uint8_t __xdata __at(0x1302) KBIRQR;

View File

@ -1,6 +1,7 @@
#ifndef _EC_PMC_H #ifndef _EC_PMC_H
#define _EC_PMC_H #define _EC_PMC_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
struct Pmc { struct Pmc {
@ -23,7 +24,7 @@ extern struct Pmc __code PMC_2;
uint8_t pmc_status(struct Pmc * pmc); uint8_t pmc_status(struct Pmc * pmc);
uint8_t pmc_read(struct Pmc * pmc); uint8_t pmc_read(struct Pmc * pmc);
void pmc_write(struct Pmc * pmc, uint8_t data); bool pmc_write(struct Pmc * pmc, uint8_t data, int timeout);
void pmc_event(struct Pmc * pmc); void pmc_event(struct Pmc * pmc);

View File

@ -17,14 +17,23 @@ uint8_t kbc_read(struct Kbc * kbc) {
return *(kbc->data_in); return *(kbc->data_in);
} }
void kbc_keyboard(struct Kbc * kbc, uint8_t data) {
//TODO: use timeout static bool kbc_wait(struct Kbc * kbc, int timeout) {
while (kbc_status(kbc) & KBC_STS_OBF) {} while (kbc_status(kbc) & KBC_STS_OBF) {
*(kbc->keyboard_out) = data; if (timeout == 0) return false;
timeout -= 1;
}
return true;
} }
void kbc_mouse(struct Kbc * kbc, uint8_t data) { bool kbc_keyboard(struct Kbc * kbc, uint8_t data, int timeout) {
//TODO: use timeout if (!kbc_wait(kbc, timeout)) return false;
while (kbc_status(kbc) & KBC_STS_OBF) {} *(kbc->keyboard_out) = data;
*(kbc->mouse_out) = data; return true;
}
bool kbc_mouse(struct Kbc * kbc, uint8_t data, int timeout) {
if (!kbc_wait(kbc, timeout)) return false;
*(kbc->mouse_out) = data;
return true;
} }

View File

@ -21,11 +21,21 @@ uint8_t pmc_read(struct Pmc * pmc) {
return *(pmc->data_in); return *(pmc->data_in);
} }
void pmc_write(struct Pmc * pmc, uint8_t data) { static bool pmc_wait(struct Pmc * pmc, int timeout) {
//TODO: use timeout while (pmc_status(pmc) & PMC_STS_OBF) {
while (pmc_status(pmc) & PMC_STS_OBF) {} if (timeout == 0) return false;
*(pmc->data_out) = data; timeout -= 1;
} }
return true;
}
bool pmc_write(struct Pmc * pmc, uint8_t data, int timeout) {
if (!pmc_wait(pmc, timeout)) return false;
*(pmc->data_out) = data;
return true;
}
#define PMC_TIMEOUT 1000
enum PmcState { enum PmcState {
PMC_STATE_DEFAULT, PMC_STATE_DEFAULT,
@ -55,7 +65,7 @@ void pmc_event(struct Pmc * pmc) {
case 0x82: case 0x82:
printf(" burst enable\n"); printf(" burst enable\n");
// TODO: figure out what burst is // TODO: figure out what burst is
pmc_write(pmc, 0x90); pmc_write(pmc, 0x90, PMC_TIMEOUT);
break; break;
case 0x83: case 0x83:
printf(" burst disable\n"); printf(" burst disable\n");
@ -64,7 +74,7 @@ void pmc_event(struct Pmc * pmc) {
case 0x84: case 0x84:
printf(" SCI queue\n"); printf(" SCI queue\n");
// TODO: queue is always empty // TODO: queue is always empty
pmc_write(pmc, 0); pmc_write(pmc, 0, PMC_TIMEOUT);
break; break;
} }
} else { } else {
@ -74,7 +84,7 @@ void pmc_event(struct Pmc * pmc) {
case PMC_STATE_ACPI_READ: case PMC_STATE_ACPI_READ:
state = PMC_STATE_DEFAULT; state = PMC_STATE_DEFAULT;
uint8_t value = acpi_read(data); uint8_t value = acpi_read(data);
pmc_write(pmc, value); pmc_write(pmc, value, PMC_TIMEOUT);
break; break;
case PMC_STATE_ACPI_WRITE: case PMC_STATE_ACPI_WRITE:
state = PMC_STATE_ACPI_WRITE_ADDR; state = PMC_STATE_ACPI_WRITE_ADDR;