Compare commits
5 Commits
e6b232851e
...
844f55c7d0
Author | SHA1 | Date |
---|---|---|
|
844f55c7d0 | |
|
a9351b222d | |
|
8fb55f56b6 | |
|
02d4f8c80e | |
|
3c1e435e04 |
|
@ -55,71 +55,54 @@ Thread KeyboardListenerBase::Listen() {
|
|||
|
||||
void KeyboardListenerBase::ListenLoop() {
|
||||
while (true) {
|
||||
auto scancode_or = server_.RecvChar();
|
||||
auto scancode_or = server_.RecvUint16();
|
||||
if (!scancode_or.ok()) {
|
||||
check(scancode_or.error());
|
||||
}
|
||||
uint8_t scancode = scancode_or.value();
|
||||
uint16_t scancode = scancode_or.value();
|
||||
|
||||
if (scancode == 0xE0) {
|
||||
extended_on_ = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Keycode k = ScancodeToKeycode(scancode);
|
||||
Action a = ScancodeToAction(scancode);
|
||||
HandleKeycode(k, a);
|
||||
Keycode k = ScancodeToKeycode(scancode & 0xFF);
|
||||
uint8_t modifiers = (scancode >> 8) & 0xFF;
|
||||
HandleKeycode(k, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardListenerBase::HandleKeycode(Keycode code, Action action) {
|
||||
void KeyboardListenerBase::HandleKeycode(Keycode code, uint8_t modifiers) {
|
||||
char c = '\0';
|
||||
|
||||
if (action == kPressed) {
|
||||
if (code >= kA && code <= kZ) {
|
||||
if (IsShift()) {
|
||||
const char* alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
c = alpha[code - kA];
|
||||
if (code >= kA && code <= kZ) {
|
||||
if (IsShift(modifiers)) {
|
||||
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 {
|
||||
const char* alpha = "abcdefghijklmnopqrstuvwxyz";
|
||||
c = alpha[code - kA];
|
||||
}
|
||||
} else if (action == kReleased) {
|
||||
if (code == kLShift) {
|
||||
lshift_ = false;
|
||||
} else if (code == kRShift) {
|
||||
rshift_ = false;
|
||||
} 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 (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') {
|
||||
|
@ -127,148 +110,114 @@ void KeyboardListenerBase::HandleKeycode(Keycode code, Action action) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Keycode KeyboardListenerBase::ScancodeToKeycode(uint16_t scancode) {
|
||||
switch (scancode) {
|
||||
case 0x01:
|
||||
return kEsc;
|
||||
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 0x0D:
|
||||
return kEquals;
|
||||
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 0x1B:
|
||||
return kRBrace;
|
||||
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 0x28:
|
||||
return kQuote;
|
||||
case 0x29:
|
||||
return kBacktick;
|
||||
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:
|
||||
case 0x05:
|
||||
return kB;
|
||||
case 0x31:
|
||||
return kN;
|
||||
case 0x32:
|
||||
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 0x33:
|
||||
return kComma;
|
||||
case 0x34:
|
||||
return kPeriod;
|
||||
case 0x35:
|
||||
return kFSlash;
|
||||
case 0x36:
|
||||
return kRShift;
|
||||
case 0x38:
|
||||
return kLAlt;
|
||||
case 0x39:
|
||||
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:
|
||||
return kEsc;
|
||||
case 0x2A:
|
||||
return kBackspace;
|
||||
case 0x2B:
|
||||
return kTab;
|
||||
case 0x2C:
|
||||
return kSpace;
|
||||
case 0x2D:
|
||||
return kMinus;
|
||||
case 0x2E:
|
||||
return kEquals;
|
||||
case 0x2F:
|
||||
return kLBrace;
|
||||
case 0x30:
|
||||
return kRBrace;
|
||||
case 0x31:
|
||||
return kBSlash;
|
||||
case 0x33:
|
||||
return kSemicolon;
|
||||
case 0x34:
|
||||
return kQuote;
|
||||
case 0x35:
|
||||
return kBacktick;
|
||||
case 0x36:
|
||||
return kComma;
|
||||
case 0x37:
|
||||
return kPeriod;
|
||||
case 0x38:
|
||||
return kFSlash;
|
||||
case 0x39:
|
||||
return kEsc; // Capslock
|
||||
}
|
||||
|
||||
dbgln("Unknown scancode {x}", scancode);
|
||||
|
@ -276,8 +225,4 @@ Keycode KeyboardListenerBase::ScancodeToKeycode(uint8_t scancode) {
|
|||
return kUnknownKeycode;
|
||||
}
|
||||
|
||||
Action KeyboardListenerBase::ScancodeToAction(uint8_t scancode) {
|
||||
return (scancode & 0x80) ? kReleased : kPressed;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
||||
|
|
|
@ -78,12 +78,6 @@ enum Keycode {
|
|||
kRight = 0x5B,
|
||||
};
|
||||
|
||||
enum Action {
|
||||
kUnknownAction,
|
||||
kPressed,
|
||||
kReleased,
|
||||
};
|
||||
|
||||
class KeyboardListenerBase {
|
||||
public:
|
||||
KeyboardListenerBase();
|
||||
|
@ -99,7 +93,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, Action action);
|
||||
virtual void HandleKeycode(Keycode code, uint8_t modifiers);
|
||||
|
||||
// This function is called by the default HandleKeycode
|
||||
// implementation if you do not override it. If it recieves
|
||||
|
@ -109,15 +103,11 @@ class KeyboardListenerBase {
|
|||
private:
|
||||
PortServer server_;
|
||||
|
||||
bool extended_on_ = false;
|
||||
Keycode ScancodeToKeycode(uint16_t scancode);
|
||||
|
||||
bool lshift_ = false;
|
||||
bool rshift_ = false;
|
||||
|
||||
Keycode ScancodeToKeycode(uint8_t scancode);
|
||||
Action ScancodeToAction(uint8_t scancode);
|
||||
|
||||
bool IsShift() { return lshift_ || rshift_; }
|
||||
bool IsShift(uint8_t modifiers) {
|
||||
return (modifiers & 0x2) || (modifiers & 0x20);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mmth
|
||||
|
|
|
@ -19,4 +19,14 @@ 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
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace mmth {
|
|||
class PortClient {
|
||||
public:
|
||||
PortClient() {}
|
||||
PortClient(z_cap_t port_cap);
|
||||
static PortClient AdoptPort(z_cap_t port_cap);
|
||||
|
||||
template <typename T>
|
||||
|
@ -18,6 +19,8 @@ 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_; }
|
||||
|
||||
|
@ -25,8 +28,6 @@ class PortClient {
|
|||
|
||||
private:
|
||||
z_cap_t port_cap_ = 0;
|
||||
|
||||
PortClient(z_cap_t port_cap);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -55,4 +55,12 @@ 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
|
||||
|
|
|
@ -19,6 +19,7 @@ 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_; }
|
||||
|
||||
|
|
|
@ -2,13 +2,24 @@
|
|||
|
||||
#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(ZIrqRegister(kZIrqKbd, &irq_cap_)); }
|
||||
KeyboardDriver::KeyboardDriver() {
|
||||
check(ZPortCreate(&port_cap_));
|
||||
gKeyboardDriver = this;
|
||||
}
|
||||
|
||||
z_cap_t KeyboardDriver::GetPortCap() { return gKeyboardDriver->port_cap_; }
|
||||
|
||||
void KeyboardDriver::RegisterListener(uint64_t port_cap) {
|
||||
listeners_.PushFront(mmth::PortClient::AdoptPort(port_cap));
|
||||
|
@ -21,13 +32,37 @@ Thread KeyboardDriver::StartInterruptLoop() {
|
|||
void KeyboardDriver::InterruptLoop() {
|
||||
dbgln("Interrupt");
|
||||
while (true) {
|
||||
uint8_t scancode;
|
||||
uint64_t num_bytes = 1;
|
||||
uint64_t scancode;
|
||||
uint64_t num_bytes = 8;
|
||||
uint64_t num_caps = 0;
|
||||
check(ZPortRecv(irq_cap_, &num_bytes, &scancode, &num_caps, nullptr));
|
||||
check(ZPortRecv(port_cap_, &num_bytes, &scancode, &num_caps, nullptr));
|
||||
|
||||
for (mmth::PortClient& client : listeners_) {
|
||||
client.WriteByte(scancode);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
bitmap_ = new_bitmap;
|
||||
}
|
||||
|
||||
void KeyboardDriver::SendKeypress(uint16_t scancode) {
|
||||
for (mmth::PortClient& client : listeners_) {
|
||||
client.Write(scancode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,19 @@ 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 irq_cap_;
|
||||
z_cap_t port_cap_;
|
||||
glcr::LinkedList<mmth::PortClient> listeners_;
|
||||
|
||||
uint64_t bitmap_ = 0;
|
||||
|
||||
void ProcessInput(uint64_t input);
|
||||
void SendKeypress(uint16_t scancode);
|
||||
};
|
||||
|
|
|
@ -15,11 +15,10 @@ uint64_t main(uint64_t init_port) {
|
|||
|
||||
YellowstoneClient yellowstone(gInitEndpointCap);
|
||||
|
||||
ASSIGN_OR_RETURN(auto xhci, XhciDriver::InitiateDriver(yellowstone));
|
||||
|
||||
dbgln("Initializing PS/2 Driver.");
|
||||
KeyboardDriver driver;
|
||||
|
||||
ASSIGN_OR_RETURN(auto xhci, XhciDriver::InitiateDriver(yellowstone));
|
||||
|
||||
dbgln("Starting PS/2 Thread.");
|
||||
Thread keyboard_thread = driver.StartInterruptLoop();
|
||||
|
||||
|
|
|
@ -80,7 +80,8 @@ 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) {
|
||||
mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(
|
||||
uint8_t config_value, glcr::UniquePtr<mmth::PortClient> client) {
|
||||
input_context_->input.add_contexts = (0x1 << 3) | 0x1;
|
||||
input_context_->input.configuration_value = config_value;
|
||||
// TODO: Maybe don't hardcode this.
|
||||
|
@ -93,7 +94,8 @@ mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(uint8_t config_value) {
|
|||
input_context_->slot_context.route_speed_entries |= (max_endpoint << 27);
|
||||
|
||||
// TODO: Dont' hardcode this.
|
||||
endpoints_[3].Initialize(input_context_->endpoint_contexts + 2);
|
||||
endpoints_[3].Initialize(input_context_->endpoint_contexts + 2,
|
||||
glcr::Move(client));
|
||||
|
||||
xhci_driver_->IssueCommand(CreateConfigureEndpointCommand(
|
||||
context_phys_ + kInputSlotContextOffset, slot_index_));
|
||||
|
|
|
@ -28,7 +28,8 @@ class DeviceSlot {
|
|||
XhciTrb CreateAddressDeviceCommand(uint8_t root_port, uint32_t route_string,
|
||||
uint16_t max_packet_size);
|
||||
|
||||
mmth::Semaphore IssueConfigureDeviceCommand(uint8_t config_value);
|
||||
mmth::Semaphore IssueConfigureDeviceCommand(
|
||||
uint8_t config_value, glcr::UniquePtr<mmth::PortClient> client);
|
||||
void SignalConfigureDeviceCompleted();
|
||||
|
||||
// Caller must keep the command in scope until it completes.
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
|
||||
#include <mammoth/util/debug.h>
|
||||
|
||||
void Endpoint::Initialize(XhciEndpointContext* context) {
|
||||
#include "xhci/trb.h"
|
||||
|
||||
void Endpoint::Initialize(XhciEndpointContext* context,
|
||||
glcr::UniquePtr<mmth::PortClient> client) {
|
||||
enabled_ = true;
|
||||
context_ = context;
|
||||
client_ = glcr::Move(client);
|
||||
|
||||
trb_ring_ = glcr::MakeUnique<TrbRingWriter>();
|
||||
recv_mem_ = mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &recv_phys_);
|
||||
|
@ -13,12 +17,7 @@ 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({
|
||||
.parameter = recv_phys_ + offset_,
|
||||
.status = 8,
|
||||
.type_and_cycle = 1 | (1 << 2) | (1 << 5) | (1 << 10),
|
||||
.control = 0,
|
||||
});
|
||||
trb_ring_->EnqueueTrb(CreateNormalTrb(recv_phys_ + offset_, 8));
|
||||
offset_ += 8;
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +25,8 @@ void Endpoint::Initialize(XhciEndpointContext* context) {
|
|||
void Endpoint::TransferComplete(uint64_t trb_phys) {
|
||||
uint64_t phys_offset =
|
||||
(trb_phys - trb_ring_->PhysicalAddress()) / sizeof(XhciTrb);
|
||||
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,
|
||||
});
|
||||
uint64_t data = *((uint64_t*)recv_mem_.vaddr() + phys_offset);
|
||||
client_->Write(data);
|
||||
trb_ring_->EnqueueTrb(CreateNormalTrb(recv_phys_ + offset_, 8));
|
||||
offset_ += 8;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <mammoth/ipc/port_client.h>
|
||||
|
||||
#include "xhci/trb_ring.h"
|
||||
#include "xhci/xhci.h"
|
||||
|
@ -9,7 +10,8 @@ class Endpoint {
|
|||
public:
|
||||
Endpoint() {}
|
||||
|
||||
void Initialize(XhciEndpointContext* context);
|
||||
void Initialize(XhciEndpointContext* context,
|
||||
glcr::UniquePtr<mmth::PortClient> client);
|
||||
|
||||
bool Enabled() { return enabled_; }
|
||||
|
||||
|
@ -24,4 +26,6 @@ class Endpoint {
|
|||
uint64_t recv_phys_;
|
||||
mmth::OwnedMemoryRegion recv_mem_;
|
||||
uint64_t offset_ = 0;
|
||||
|
||||
glcr::UniquePtr<mmth::PortClient> client_;
|
||||
};
|
||||
|
|
|
@ -4,6 +4,8 @@ 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 {
|
||||
|
@ -18,6 +20,16 @@ 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,
|
||||
|
|
|
@ -29,6 +29,7 @@ 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();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#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"
|
||||
|
@ -75,7 +76,9 @@ void configure_device(void* void_device_slot) {
|
|||
config_descriptor->configuration_value);
|
||||
|
||||
device_slot
|
||||
->IssueConfigureDeviceCommand(config_descriptor->configuration_value)
|
||||
->IssueConfigureDeviceCommand(
|
||||
config_descriptor->configuration_value,
|
||||
glcr::MakeUnique<mmth::PortClient>(KeyboardDriver::GetPortCap()))
|
||||
.Wait();
|
||||
|
||||
dbgln("Configured!");
|
||||
|
|
|
@ -49,6 +49,10 @@ 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());
|
||||
|
|
|
@ -113,6 +113,8 @@ 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());
|
||||
}
|
||||
|
@ -138,4 +140,6 @@ void YellowstoneServer::WaitVictoriaFallsRegistered() {
|
|||
has_victoriafalls_semaphore_.Wait();
|
||||
}
|
||||
|
||||
void YellowstoneServer::WaitVoyageursRegistered() { has_voyageurs_.Wait(); }
|
||||
|
||||
} // namespace yellowstone
|
||||
|
|
|
@ -25,6 +25,7 @@ class YellowstoneServer : public YellowstoneServerBase {
|
|||
|
||||
void WaitDenaliRegistered();
|
||||
void WaitVictoriaFallsRegistered();
|
||||
void WaitVoyageursRegistered();
|
||||
|
||||
private:
|
||||
glcr::HashMap<glcr::String, z_cap_t> endpoint_map_;
|
||||
|
@ -37,6 +38,7 @@ class YellowstoneServer : public YellowstoneServerBase {
|
|||
|
||||
mmth::Semaphore has_denali_semaphore_;
|
||||
mmth::Semaphore has_victoriafalls_semaphore_;
|
||||
mmth::Semaphore has_voyageurs_;
|
||||
|
||||
YellowstoneServer(z_cap_t endpoint_cap);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue