Compare commits

..

No commits in common. "844f55c7d0f55542efd73574ea13a18d29167f84" and "e6b232851e16590c3d79cc411c431fa0bb0723ff" have entirely different histories.

19 changed files with 232 additions and 256 deletions

View File

@ -55,54 +55,71 @@ Thread KeyboardListenerBase::Listen() {
void KeyboardListenerBase::ListenLoop() {
while (true) {
auto scancode_or = server_.RecvUint16();
auto scancode_or = server_.RecvChar();
if (!scancode_or.ok()) {
check(scancode_or.error());
}
uint16_t scancode = scancode_or.value();
uint8_t scancode = scancode_or.value();
Keycode k = ScancodeToKeycode(scancode & 0xFF);
uint8_t modifiers = (scancode >> 8) & 0xFF;
HandleKeycode(k, modifiers);
if (scancode == 0xE0) {
extended_on_ = true;
continue;
}
Keycode k = ScancodeToKeycode(scancode);
Action a = ScancodeToAction(scancode);
HandleKeycode(k, a);
}
}
void KeyboardListenerBase::HandleKeycode(Keycode code, uint8_t modifiers) {
void KeyboardListenerBase::HandleKeycode(Keycode code, Action action) {
char c = '\0';
if (code >= kA && code <= kZ) {
if (IsShift(modifiers)) {
const char* alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
c = alpha[code - kA];
if (action == kPressed) {
if (code >= kA && code <= kZ) {
if (IsShift()) {
const char* alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
c = alpha[code - kA];
} else {
const char* alpha = "abcdefghijklmnopqrstuvwxyz";
c = alpha[code - kA];
} else {
const char* alpha = "abcdefghijklmnopqrstuvwxyz";
c = alpha[code - kA];
}
} else if (code >= k1 && code <= k0) {
if (IsShift()) {
const char* num = "!@#$%^&*()";
c = num[code - k1];
} else {
const char* num = "1234567890";
c = num[code - k1];
}
} else if (code >= kMinus && code <= kBacktick) {
if (IsShift()) {
const char* sym = "_+{}|?:\"<>~";
c = sym[code - kMinus];
} else {
const char* sym = "-=[]\\/;',.`";
c = sym[code - kMinus];
}
} else if (code == kEnter) {
c = '\n';
} else if (code == kSpace) {
c = ' ';
} else if (code == kTab) {
c = '\t';
} else if (code == kBackspace) {
c = '\b';
} else if (code == kLShift) {
lshift_ = true;
} else if (code == kRShift) {
rshift_ = true;
}
} else if (code >= k1 && code <= k0) {
if (IsShift(modifiers)) {
const char* num = "!@#$%^&*()";
c = num[code - k1];
} else {
const char* num = "1234567890";
c = num[code - k1];
} else if (action == kReleased) {
if (code == kLShift) {
lshift_ = false;
} else if (code == kRShift) {
rshift_ = false;
}
} else if (code >= kMinus && code <= kBacktick) {
if (IsShift(modifiers)) {
const char* sym = "_+{}|?:\"<>~";
c = sym[code - kMinus];
} else {
const char* sym = "-=[]\\/;',.`";
c = sym[code - kMinus];
}
} else if (code == kEnter) {
c = '\n';
} else if (code == kSpace) {
c = ' ';
} else if (code == kTab) {
c = '\t';
} else if (code == kBackspace) {
c = '\b';
}
if (c != '\0') {
@ -110,114 +127,148 @@ void KeyboardListenerBase::HandleKeycode(Keycode code, uint8_t modifiers) {
}
}
Keycode KeyboardListenerBase::ScancodeToKeycode(uint16_t scancode) {
Keycode KeyboardListenerBase::ScancodeToKeycode(uint8_t scancode) {
// Cancel out the released bit.
scancode &= 0x7F;
if (extended_on_) {
extended_on_ = false;
switch (scancode) {
case 0x1D:
return kRCtrl;
case 0x38:
return kRAlt;
case 0x48:
return kUp;
case 0x4B:
return kLeft;
case 0x4D:
return kRight;
case 0x50:
return kDown;
case 0x53:
return kDelete;
case 0x5B:
return kSuper;
}
dbgln("Unknown extended scancode {x}", scancode);
return kUnknownKeycode;
}
switch (scancode) {
case 0x04:
return kA;
case 0x05:
return kB;
case 0x06:
return kC;
case 0x07:
return kD;
case 0x08:
return kE;
case 0x09:
return kF;
case 0x0A:
return kG;
case 0x0B:
return kH;
case 0x0C:
return kI;
case 0x0D:
return kJ;
case 0x0E:
return kK;
case 0x0F:
return kL;
case 0x10:
return kM;
case 0x11:
return kN;
case 0x12:
return kO;
case 0x13:
return kP;
case 0x14:
return kQ;
case 0x15:
return kR;
case 0x16:
return kS;
case 0x17:
return kT;
case 0x18:
return kU;
case 0x19:
return kV;
case 0x1A:
return kW;
case 0x1B:
return kX;
case 0x1C:
return kY;
case 0x1D:
return kZ;
case 0x1E:
return k1;
case 0x1F:
return k2;
case 0x20:
return k3;
case 0x21:
return k4;
case 0x22:
return k5;
case 0x23:
return k6;
case 0x24:
return k7;
case 0x25:
return k8;
case 0x26:
return k9;
case 0x27:
return k0;
case 0x28:
return kEnter;
case 0x29:
case 0x01:
return kEsc;
case 0x2A:
return kBackspace;
case 0x2B:
return kTab;
case 0x2C:
return kSpace;
case 0x2D:
case 0x02:
return k1;
case 0x03:
return k2;
case 0x04:
return k3;
case 0x05:
return k4;
case 0x06:
return k5;
case 0x07:
return k6;
case 0x08:
return k7;
case 0x09:
return k8;
case 0x0A:
return k9;
case 0x0B:
return k0;
case 0x0C:
return kMinus;
case 0x2E:
case 0x0D:
return kEquals;
case 0x2F:
case 0x0E:
return kBackspace;
case 0x0F:
return kTab;
case 0x10:
return kQ;
case 0x11:
return kW;
case 0x12:
return kE;
case 0x13:
return kR;
case 0x14:
return kT;
case 0x15:
return kY;
case 0x16:
return kU;
case 0x17:
return kI;
case 0x18:
return kO;
case 0x19:
return kP;
case 0x1A:
return kLBrace;
case 0x30:
case 0x1B:
return kRBrace;
case 0x31:
return kBSlash;
case 0x33:
case 0x1C:
return kEnter;
case 0x1D:
return kLCtrl;
case 0x1E:
return kA;
case 0x1F:
return kS;
case 0x20:
return kD;
case 0x21:
return kF;
case 0x22:
return kG;
case 0x23:
return kH;
case 0x24:
return kJ;
case 0x25:
return kK;
case 0x26:
return kL;
case 0x27:
return kSemicolon;
case 0x34:
case 0x28:
return kQuote;
case 0x35:
case 0x29:
return kBacktick;
case 0x36:
case 0x2A:
return kLShift;
case 0x2B:
return kBSlash;
case 0x2C:
return kZ;
case 0x2D:
return kX;
case 0x2E:
return kC;
case 0x2F:
return kV;
case 0x30:
return kB;
case 0x31:
return kN;
case 0x32:
return kM;
case 0x33:
return kComma;
case 0x37:
case 0x34:
return kPeriod;
case 0x38:
case 0x35:
return kFSlash;
case 0x36:
return kRShift;
case 0x38:
return kLAlt;
case 0x39:
return kEsc; // Capslock
return kSpace;
}
dbgln("Unknown scancode {x}", scancode);
@ -225,4 +276,8 @@ Keycode KeyboardListenerBase::ScancodeToKeycode(uint16_t scancode) {
return kUnknownKeycode;
}
Action KeyboardListenerBase::ScancodeToAction(uint8_t scancode) {
return (scancode & 0x80) ? kReleased : kPressed;
}
} // namespace mmth

View File

@ -78,6 +78,12 @@ enum Keycode {
kRight = 0x5B,
};
enum Action {
kUnknownAction,
kPressed,
kReleased,
};
class KeyboardListenerBase {
public:
KeyboardListenerBase();
@ -93,7 +99,7 @@ class KeyboardListenerBase {
// Override this to recieve all raw keycodes. By default
// this function will try to translate each keycode into
// a printable character and call HandleCharacter.
virtual void HandleKeycode(Keycode code, uint8_t modifiers);
virtual void HandleKeycode(Keycode code, Action action);
// This function is called by the default HandleKeycode
// implementation if you do not override it. If it recieves
@ -103,11 +109,15 @@ class KeyboardListenerBase {
private:
PortServer server_;
Keycode ScancodeToKeycode(uint16_t scancode);
bool extended_on_ = false;
bool IsShift(uint8_t modifiers) {
return (modifiers & 0x2) || (modifiers & 0x20);
}
bool lshift_ = false;
bool rshift_ = false;
Keycode ScancodeToKeycode(uint8_t scancode);
Action ScancodeToAction(uint8_t scancode);
bool IsShift() { return lshift_ || rshift_; }
};
} // namespace mmth

View File

@ -19,14 +19,4 @@ glcr::ErrorCode PortClient::WriteByte(uint8_t byte) {
return static_cast<glcr::ErrorCode>(
ZPortSend(port_cap_, 1, &byte, 0, nullptr));
}
glcr::ErrorCode PortClient::Write(uint16_t data) {
return static_cast<glcr::ErrorCode>(
ZPortSend(port_cap_, 2, &data, 0, nullptr));
}
glcr::ErrorCode PortClient::Write(uint64_t data) {
return static_cast<glcr::ErrorCode>(
ZPortSend(port_cap_, 8, &data, 0, nullptr));
}
} // namespace mmth

View File

@ -10,7 +10,6 @@ namespace mmth {
class PortClient {
public:
PortClient() {}
PortClient(z_cap_t port_cap);
static PortClient AdoptPort(z_cap_t port_cap);
template <typename T>
@ -19,8 +18,6 @@ class PortClient {
glcr::ErrorCode WriteString(glcr::String str, z_cap_t cap);
glcr::ErrorCode WriteByte(uint8_t byte);
glcr::ErrorCode Write(uint16_t data);
glcr::ErrorCode Write(uint64_t data);
z_cap_t cap() { return port_cap_; }
@ -28,6 +25,8 @@ class PortClient {
private:
z_cap_t port_cap_ = 0;
PortClient(z_cap_t port_cap);
};
template <typename T>

View File

@ -55,12 +55,4 @@ glcr::ErrorOr<char> PortServer::RecvChar() {
return byte;
}
glcr::ErrorOr<uint16_t> PortServer::RecvUint16() {
uint64_t bytes = 2;
uint64_t caps = 0;
uint16_t data;
RET_ERR(ZPortRecv(port_cap_, &bytes, &data, &caps, nullptr));
return data;
}
} // namespace mmth

View File

@ -19,7 +19,6 @@ class PortServer {
glcr::ErrorCode PollForIntCap(uint64_t* msg, uint64_t* cap);
glcr::ErrorOr<char> RecvChar();
glcr::ErrorOr<uint16_t> RecvUint16();
z_cap_t cap() { return port_cap_; }

View File

@ -2,24 +2,13 @@
#include <mammoth/util/debug.h>
namespace {
KeyboardDriver* gKeyboardDriver = nullptr;
}
void InterruptEnter(void* void_keyboard) {
KeyboardDriver* keyboard = static_cast<KeyboardDriver*>(void_keyboard);
keyboard->InterruptLoop();
}
KeyboardDriver::KeyboardDriver() {
check(ZPortCreate(&port_cap_));
gKeyboardDriver = this;
}
z_cap_t KeyboardDriver::GetPortCap() { return gKeyboardDriver->port_cap_; }
KeyboardDriver::KeyboardDriver() { check(ZIrqRegister(kZIrqKbd, &irq_cap_)); }
void KeyboardDriver::RegisterListener(uint64_t port_cap) {
listeners_.PushFront(mmth::PortClient::AdoptPort(port_cap));
@ -32,37 +21,13 @@ Thread KeyboardDriver::StartInterruptLoop() {
void KeyboardDriver::InterruptLoop() {
dbgln("Interrupt");
while (true) {
uint64_t scancode;
uint64_t num_bytes = 8;
uint8_t scancode;
uint64_t num_bytes = 1;
uint64_t num_caps = 0;
check(ZPortRecv(port_cap_, &num_bytes, &scancode, &num_caps, nullptr));
check(ZPortRecv(irq_cap_, &num_bytes, &scancode, &num_caps, nullptr));
ProcessInput(scancode);
}
}
void KeyboardDriver::ProcessInput(uint64_t input) {
uint16_t modifiers = (input & 0xFF) << 8;
uint64_t new_bitmap = 0;
for (uint8_t i = 2; i < 8; i++) {
uint8_t code = (input >> (8 * i)) & 0xFF;
if (code == 0) {
break;
}
if (code >= 64) {
dbgln("Skipping keycode: {x}", code);
}
uint64_t bit = 1 << code;
new_bitmap |= bit;
if ((bitmap_ & bit) != bit) {
SendKeypress(modifiers | code);
for (mmth::PortClient& client : listeners_) {
client.WriteByte(scancode);
}
}
bitmap_ = new_bitmap;
}
void KeyboardDriver::SendKeypress(uint16_t scancode) {
for (mmth::PortClient& client : listeners_) {
client.Write(scancode);
}
}

View File

@ -11,19 +11,12 @@ class KeyboardDriver {
KeyboardDriver(const KeyboardDriver&) = delete;
KeyboardDriver(KeyboardDriver&&) = delete;
static z_cap_t GetPortCap();
void RegisterListener(uint64_t port_cap);
Thread StartInterruptLoop();
void InterruptLoop();
private:
z_cap_t port_cap_;
z_cap_t irq_cap_;
glcr::LinkedList<mmth::PortClient> listeners_;
uint64_t bitmap_ = 0;
void ProcessInput(uint64_t input);
void SendKeypress(uint16_t scancode);
};

View File

@ -15,10 +15,11 @@ uint64_t main(uint64_t init_port) {
YellowstoneClient yellowstone(gInitEndpointCap);
KeyboardDriver driver;
ASSIGN_OR_RETURN(auto xhci, XhciDriver::InitiateDriver(yellowstone));
dbgln("Initializing PS/2 Driver.");
KeyboardDriver driver;
dbgln("Starting PS/2 Thread.");
Thread keyboard_thread = driver.StartInterruptLoop();

View File

@ -80,8 +80,7 @@ void DeviceSlot::TransferComplete(uint8_t endpoint_index, uint64_t trb_phys) {
check(control_completion_sempahores_.Delete(trb_phys));
}
mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(
uint8_t config_value, glcr::UniquePtr<mmth::PortClient> client) {
mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(uint8_t config_value) {
input_context_->input.add_contexts = (0x1 << 3) | 0x1;
input_context_->input.configuration_value = config_value;
// TODO: Maybe don't hardcode this.
@ -94,8 +93,7 @@ mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(
input_context_->slot_context.route_speed_entries |= (max_endpoint << 27);
// TODO: Dont' hardcode this.
endpoints_[3].Initialize(input_context_->endpoint_contexts + 2,
glcr::Move(client));
endpoints_[3].Initialize(input_context_->endpoint_contexts + 2);
xhci_driver_->IssueCommand(CreateConfigureEndpointCommand(
context_phys_ + kInputSlotContextOffset, slot_index_));

View File

@ -28,8 +28,7 @@ class DeviceSlot {
XhciTrb CreateAddressDeviceCommand(uint8_t root_port, uint32_t route_string,
uint16_t max_packet_size);
mmth::Semaphore IssueConfigureDeviceCommand(
uint8_t config_value, glcr::UniquePtr<mmth::PortClient> client);
mmth::Semaphore IssueConfigureDeviceCommand(uint8_t config_value);
void SignalConfigureDeviceCompleted();
// Caller must keep the command in scope until it completes.

View File

@ -2,13 +2,9 @@
#include <mammoth/util/debug.h>
#include "xhci/trb.h"
void Endpoint::Initialize(XhciEndpointContext* context,
glcr::UniquePtr<mmth::PortClient> client) {
void Endpoint::Initialize(XhciEndpointContext* context) {
enabled_ = true;
context_ = context;
client_ = glcr::Move(client);
trb_ring_ = glcr::MakeUnique<TrbRingWriter>();
recv_mem_ = mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &recv_phys_);
@ -17,7 +13,12 @@ void Endpoint::Initialize(XhciEndpointContext* context,
context_->error_and_type = (0x3 << 1) | (0x7 << 3) | (0x8 << 16);
for (uint64_t i = 0; i < 10; i++) {
trb_ring_->EnqueueTrb(CreateNormalTrb(recv_phys_ + offset_, 8));
trb_ring_->EnqueueTrb({
.parameter = recv_phys_ + offset_,
.status = 8,
.type_and_cycle = 1 | (1 << 2) | (1 << 5) | (1 << 10),
.control = 0,
});
offset_ += 8;
}
}
@ -25,8 +26,12 @@ void Endpoint::Initialize(XhciEndpointContext* context,
void Endpoint::TransferComplete(uint64_t trb_phys) {
uint64_t phys_offset =
(trb_phys - trb_ring_->PhysicalAddress()) / sizeof(XhciTrb);
uint64_t data = *((uint64_t*)recv_mem_.vaddr() + phys_offset);
client_->Write(data);
trb_ring_->EnqueueTrb(CreateNormalTrb(recv_phys_ + offset_, 8));
dbgln("Data: {x}", *((uint64_t*)recv_mem_.vaddr() + phys_offset));
trb_ring_->EnqueueTrb({
.parameter = recv_phys_ + offset_,
.status = 8,
.type_and_cycle = 1 | (1 << 2) | (1 << 5) | (1 << 10),
.control = 0,
});
offset_ += 8;
}

View File

@ -1,7 +1,6 @@
#pragma once
#include <glacier/memory/unique_ptr.h>
#include <mammoth/ipc/port_client.h>
#include "xhci/trb_ring.h"
#include "xhci/xhci.h"
@ -10,8 +9,7 @@ class Endpoint {
public:
Endpoint() {}
void Initialize(XhciEndpointContext* context,
glcr::UniquePtr<mmth::PortClient> client);
void Initialize(XhciEndpointContext* context);
bool Enabled() { return enabled_; }
@ -26,6 +24,4 @@ class Endpoint {
uint64_t recv_phys_;
mmth::OwnedMemoryRegion recv_mem_;
uint64_t offset_ = 0;
glcr::UniquePtr<mmth::PortClient> client_;
};

View File

@ -4,8 +4,6 @@ constexpr uint8_t kTrb_TypeOffset = 10;
constexpr uint16_t kTrb_Cycle = 1;
constexpr uint16_t kTrb_ToggleCycle = (1 << 1);
constexpr uint16_t kTrb_InterruptShortPacket = (1 << 2);
constexpr uint16_t kTrb_Interrupt = (1 << 5);
constexpr uint16_t kTrb_BSR = (1 << 9);
namespace {
@ -20,16 +18,6 @@ TrbType GetType(const XhciTrb& trb) {
return TrbType(trb.type_and_cycle >> kTrb_TypeOffset);
}
XhciTrb CreateNormalTrb(uint64_t physical_address, uint8_t size) {
return {
.parameter = physical_address,
.status = size,
.type_and_cycle = (uint16_t)(TypeToInt(TrbType::Normal) | kTrb_Cycle |
kTrb_Interrupt | kTrb_InterruptShortPacket),
.control = 0,
};
}
XhciTrb CreateLinkTrb(uint64_t physical_address) {
return {
.parameter = physical_address,

View File

@ -29,7 +29,6 @@ enum class TrbType : uint8_t {
TrbType GetType(const XhciTrb& trb);
XhciTrb CreateNormalTrb(uint64_t physical_address, uint8_t size);
XhciTrb CreateLinkTrb(uint64_t physical_address);
XhciTrb CreateEnableSlotTrb();

View File

@ -5,7 +5,6 @@
#include <mammoth/util/memory_region.h>
#include <zcall.h>
#include "keyboard/keyboard_driver.h"
#include "xhci/descriptors.h"
#include "xhci/trb.h"
#include "xhci/xhci.h"
@ -76,9 +75,7 @@ void configure_device(void* void_device_slot) {
config_descriptor->configuration_value);
device_slot
->IssueConfigureDeviceCommand(
config_descriptor->configuration_value,
glcr::MakeUnique<mmth::PortClient>(KeyboardDriver::GetPortCap()))
->IssueConfigureDeviceCommand(config_descriptor->configuration_value)
.Wait();
dbgln("Configured!");

View File

@ -49,10 +49,6 @@ uint64_t main(uint64_t port_cap) {
for (glcr::StringView& file : files) {
if (!file.empty()) {
// TODO: Implement startup dependencies.
if (file == "teton") {
server->WaitVoyageursRegistered();
}
mmth::File binary = mmth::File::Open(glcr::StrFormat("/bin/{}", file));
ASSIGN_OR_RETURN(client_cap, server->CreateClientCap());

View File

@ -113,8 +113,6 @@ glcr::Status YellowstoneServer::HandleRegisterEndpoint(
// transmit to other processes.
mmth::SetVfsCap(req.endpoint_capability());
has_victoriafalls_semaphore_.Signal();
} else if (req.endpoint_name() == "voyageurs") {
has_voyageurs_.Signal();
} else {
dbgln("[WARN] Got endpoint cap type: {}", req.endpoint_name().cstr());
}
@ -140,6 +138,4 @@ void YellowstoneServer::WaitVictoriaFallsRegistered() {
has_victoriafalls_semaphore_.Wait();
}
void YellowstoneServer::WaitVoyageursRegistered() { has_voyageurs_.Wait(); }
} // namespace yellowstone

View File

@ -25,7 +25,6 @@ class YellowstoneServer : public YellowstoneServerBase {
void WaitDenaliRegistered();
void WaitVictoriaFallsRegistered();
void WaitVoyageursRegistered();
private:
glcr::HashMap<glcr::String, z_cap_t> endpoint_map_;
@ -38,7 +37,6 @@ class YellowstoneServer : public YellowstoneServerBase {
mmth::Semaphore has_denali_semaphore_;
mmth::Semaphore has_victoriafalls_semaphore_;
mmth::Semaphore has_voyageurs_;
YellowstoneServer(z_cap_t endpoint_cap);
};