Add timeout for kbc and pmc writes
This commit is contained in:
parent
4269b25ecf
commit
1f87adb1fc
@ -6,7 +6,7 @@
|
||||
#include <ec/kbc.h>
|
||||
|
||||
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);
|
||||
|
||||
#endif // _BOARD_KBC_H
|
||||
|
@ -10,20 +10,22 @@ void kbc_init(void) {
|
||||
*(KBC.control) = 0;
|
||||
}
|
||||
|
||||
#define KBC_TIMEOUT 1000
|
||||
|
||||
// System flag
|
||||
static bool kbc_system = false;
|
||||
// Translate from scancode set 2 to scancode set 1
|
||||
// for basically no good reason
|
||||
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) {
|
||||
key = keymap_translate(key);
|
||||
}
|
||||
switch (key & 0xFF00) {
|
||||
case K_E0:
|
||||
printf(" E0\n");
|
||||
kbc_keyboard(kbc, 0xE0);
|
||||
if (!kbc_keyboard(kbc, 0xE0, KBC_TIMEOUT)) return false;
|
||||
key &= 0xFF;
|
||||
// Fall through
|
||||
case 0x00:
|
||||
@ -32,13 +34,14 @@ void kbc_key(struct Kbc * kbc, uint16_t key, bool pressed) {
|
||||
key |= 0x80;
|
||||
} else {
|
||||
printf(" F0\n");
|
||||
kbc_keyboard(kbc, 0xF0);
|
||||
if (!kbc_keyboard(kbc, 0xF0, KBC_TIMEOUT)) return false;
|
||||
}
|
||||
}
|
||||
printf(" %02X\n", key);
|
||||
kbc_keyboard(kbc, (uint8_t)key);
|
||||
if (!kbc_keyboard(kbc, (uint8_t)key, KBC_TIMEOUT)) return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enum KbcState {
|
||||
@ -84,12 +87,12 @@ void kbc_event(struct Kbc * kbc) {
|
||||
case 0xAA:
|
||||
printf(" test controller\n");
|
||||
// Why not pass the test?
|
||||
kbc_keyboard(kbc, 0x55);
|
||||
kbc_keyboard(kbc, 0x55, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xAB:
|
||||
printf(" test first port\n");
|
||||
// We _ARE_ the keyboard, so everything is good.
|
||||
kbc_keyboard(kbc, 0x00);
|
||||
kbc_keyboard(kbc, 0x00, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xAD:
|
||||
printf(" disable first port\n");
|
||||
@ -112,33 +115,34 @@ void kbc_event(struct Kbc * kbc) {
|
||||
case 0xED:
|
||||
printf(" set leds\n");
|
||||
state = KBC_STATE_SET_LEDS;
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xEE:
|
||||
printf(" echo\n");
|
||||
// Hey, this is easy. I like easy commands
|
||||
kbc_keyboard(kbc, 0xEE);
|
||||
kbc_keyboard(kbc, 0xEE, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF0:
|
||||
printf(" get/set scancode\n");
|
||||
state = KBC_STATE_SCANCODE;
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF4:
|
||||
printf(" enable scanning\n");
|
||||
kbscan_enabled = true;
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF5:
|
||||
printf(" disable scanning\n");
|
||||
kbscan_enabled = false;
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xFF:
|
||||
printf(" self test\n");
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
// Yep, everything is still good, I promise
|
||||
kbc_keyboard(kbc, 0xAA);
|
||||
if (kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT)) {
|
||||
// Yep, everything is still good, I promise
|
||||
kbc_keyboard(kbc, 0xAA, KBC_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -171,7 +175,7 @@ void kbc_event(struct Kbc * kbc) {
|
||||
case KBC_STATE_SET_LEDS:
|
||||
printf(" set leds\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_SCANCODE:
|
||||
printf(" get/set scancode\n");
|
||||
@ -181,7 +185,7 @@ void kbc_event(struct Kbc * kbc) {
|
||||
printf(" set scancode set 2\n");
|
||||
break;
|
||||
}
|
||||
kbc_keyboard(kbc, 0xFA);
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_WRITE_PORT:
|
||||
printf(" write port byte\n");
|
||||
|
@ -51,7 +51,7 @@ void kbscan_event(void) {
|
||||
uint16_t key = keymap(i, j, kbscan_layer);
|
||||
printf("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b);
|
||||
if (kbscan_enabled && key) {
|
||||
kbc_key(&KBC, key, new_b);
|
||||
kbc_scancode(&KBC, key, new_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef _EC_KBC_H
|
||||
#define _EC_KBC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void kbc_init(void);
|
||||
@ -28,8 +29,8 @@ extern struct Kbc __code KBC;
|
||||
|
||||
uint8_t kbc_status(struct Kbc * kbc);
|
||||
uint8_t kbc_read(struct Kbc * kbc);
|
||||
void kbc_keyboard(struct Kbc * kbc, uint8_t data);
|
||||
void kbc_mouse(struct Kbc * kbc, uint8_t data);
|
||||
bool kbc_keyboard(struct Kbc * kbc, uint8_t data, int timeout);
|
||||
bool kbc_mouse(struct Kbc * kbc, uint8_t data, int timeout);
|
||||
|
||||
volatile uint8_t __xdata __at(0x1300) KBHICR;
|
||||
volatile uint8_t __xdata __at(0x1302) KBIRQR;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef _EC_PMC_H
|
||||
#define _EC_PMC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct Pmc {
|
||||
@ -23,7 +24,7 @@ extern struct Pmc __code PMC_2;
|
||||
|
||||
uint8_t pmc_status(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);
|
||||
|
||||
|
@ -17,14 +17,23 @@ uint8_t kbc_read(struct Kbc * kbc) {
|
||||
return *(kbc->data_in);
|
||||
}
|
||||
|
||||
void kbc_keyboard(struct Kbc * kbc, uint8_t data) {
|
||||
//TODO: use timeout
|
||||
while (kbc_status(kbc) & KBC_STS_OBF) {}
|
||||
*(kbc->keyboard_out) = data;
|
||||
|
||||
static bool kbc_wait(struct Kbc * kbc, int timeout) {
|
||||
while (kbc_status(kbc) & KBC_STS_OBF) {
|
||||
if (timeout == 0) return false;
|
||||
timeout -= 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void kbc_mouse(struct Kbc * kbc, uint8_t data) {
|
||||
//TODO: use timeout
|
||||
while (kbc_status(kbc) & KBC_STS_OBF) {}
|
||||
*(kbc->mouse_out) = data;
|
||||
bool kbc_keyboard(struct Kbc * kbc, uint8_t data, int timeout) {
|
||||
if (!kbc_wait(kbc, timeout)) return false;
|
||||
*(kbc->keyboard_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;
|
||||
}
|
||||
|
@ -21,12 +21,22 @@ uint8_t pmc_read(struct Pmc * pmc) {
|
||||
return *(pmc->data_in);
|
||||
}
|
||||
|
||||
void pmc_write(struct Pmc * pmc, uint8_t data) {
|
||||
//TODO: use timeout
|
||||
while (pmc_status(pmc) & PMC_STS_OBF) {}
|
||||
*(pmc->data_out) = data;
|
||||
static bool pmc_wait(struct Pmc * pmc, int timeout) {
|
||||
while (pmc_status(pmc) & PMC_STS_OBF) {
|
||||
if (timeout == 0) return false;
|
||||
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 {
|
||||
PMC_STATE_DEFAULT,
|
||||
PMC_STATE_ACPI_READ,
|
||||
@ -55,7 +65,7 @@ void pmc_event(struct Pmc * pmc) {
|
||||
case 0x82:
|
||||
printf(" burst enable\n");
|
||||
// TODO: figure out what burst is
|
||||
pmc_write(pmc, 0x90);
|
||||
pmc_write(pmc, 0x90, PMC_TIMEOUT);
|
||||
break;
|
||||
case 0x83:
|
||||
printf(" burst disable\n");
|
||||
@ -64,7 +74,7 @@ void pmc_event(struct Pmc * pmc) {
|
||||
case 0x84:
|
||||
printf(" SCI queue\n");
|
||||
// TODO: queue is always empty
|
||||
pmc_write(pmc, 0);
|
||||
pmc_write(pmc, 0, PMC_TIMEOUT);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -74,7 +84,7 @@ void pmc_event(struct Pmc * pmc) {
|
||||
case PMC_STATE_ACPI_READ:
|
||||
state = PMC_STATE_DEFAULT;
|
||||
uint8_t value = acpi_read(data);
|
||||
pmc_write(pmc, value);
|
||||
pmc_write(pmc, value, PMC_TIMEOUT);
|
||||
break;
|
||||
case PMC_STATE_ACPI_WRITE:
|
||||
state = PMC_STATE_ACPI_WRITE_ADDR;
|
||||
|
Loading…
x
Reference in New Issue
Block a user