From bb3b6b02605b65787dd3474aa186a4bcb638fd9d Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sat, 4 Jan 2014 01:28:59 +0100 Subject: [PATCH] Update kernel/kb/ps2.{cpp,h} to current coding conventions. --- kernel/kb/ps2.cpp | 402 ++++++++++++++++++++++++---------------------- kernel/kb/ps2.h | 74 +++++---- 2 files changed, 247 insertions(+), 229 deletions(-) diff --git a/kernel/kb/ps2.cpp b/kernel/kb/ps2.cpp index 58ccc7e0..9803785b 100644 --- a/kernel/kb/ps2.cpp +++ b/kernel/kb/ps2.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. This file is part of Sortix. @@ -23,6 +23,8 @@ *******************************************************************************/ #include +#include +#include #include #include @@ -36,198 +38,210 @@ #include "ps2.h" -namespace Sortix +namespace Sortix { + +const uint16_t DATA = 0x0; +const uint16_t COMMAND = 0x0; +const uint16_t STATUS = 0x4; +const uint8_t CMD_SETLED = 0xED; +const uint8_t LED_SCRLCK = 1 << 0; +const uint8_t LED_NUMLCK = 1 << 1; +const uint8_t LED_CAPSLCK = 1 << 2; + +void PS2Keyboard__OnInterrupt(CPU::InterruptRegisters* regs, void* user) { - const uint16_t DATA = 0x0; - const uint16_t COMMAND = 0x0; - const uint16_t STATUS = 0x4; - const uint8_t CMD_SETLED = 0xED; - const uint8_t LED_SCRLCK = (1<<0); - const uint8_t LED_NUMLCK = (1<<1); - const uint8_t LED_CAPSLCK = (1<<2); - - void PS2Keyboard__OnInterrupt(CPU::InterruptRegisters* regs, void* user) - { - ((PS2Keyboard*) user)->OnInterrupt(regs); - } - - PS2Keyboard::PS2Keyboard(uint16_t iobase, uint8_t interrupt) - { - this->queue = NULL; - this->queuelength = 0; - this->queueoffset = 0; - this->queueused = 0; - this->owner = NULL; - this->ownerptr = NULL; - this->iobase = iobase; - this->interrupt = interrupt; - this->leds = 0; - this->scancodeescaped = false; - this->kblock = KTHREAD_MUTEX_INITIALIZER; - Interrupt::RegisterHandler(interrupt, PS2Keyboard__OnInterrupt, this); - - // If any scancodes were already pending, our interrupt handler will - // never be called. Let's just discard anything pending. - PopScancode(); - } - - PS2Keyboard::~PS2Keyboard() - { - Interrupt::RegisterHandler(interrupt, NULL, NULL); - delete[] queue; - } - - struct PS2KeyboardWork - { - PS2Keyboard* kb; - uint8_t scancode; - }; - - static void PS2Keyboard__InterruptWork(void* payload, size_t size) - { - assert(size == sizeof(PS2KeyboardWork)); - PS2KeyboardWork* work = (PS2KeyboardWork*) payload; - work->kb->InterruptWork(work->scancode); - } - - void PS2Keyboard::OnInterrupt(CPU::InterruptRegisters* regs) - { - uint8_t scancode = PopScancode(); - if ( scancode == KBKEY_F10 ) - { - CurrentThread()->SaveRegisters(regs); - Debugger::Run(); - } - PS2KeyboardWork work; - work.kb = this; - work.scancode = scancode; - Interrupt::ScheduleWork(PS2Keyboard__InterruptWork, &work, sizeof(work)); - } - - void PS2Keyboard::InterruptWork(uint8_t scancode) - { - kthread_mutex_lock(&kblock); - int kbkey = DecodeScancode(scancode); - if ( !kbkey ) { kthread_mutex_unlock(&kblock); return; } - - if ( !PushKey(kbkey) ) - { - Log::PrintF("Warning: dropping keystroke due to insufficient " - "storage space in PS2 keyboard driver.\n"); - kthread_mutex_unlock(&kblock); - return; - } - - uint8_t newleds = leds; - - if ( kbkey == KBKEY_CAPSLOCK ) { newleds ^= LED_CAPSLCK; } - if ( kbkey == KBKEY_SCROLLLOCK ) { newleds ^= LED_SCRLCK; } - if ( kbkey == KBKEY_NUMLOCK ) { newleds ^= LED_NUMLCK; } - - if ( newleds != leds ) { UpdateLEDs(leds = newleds); } - - kthread_mutex_unlock(&kblock); - - NotifyOwner(); - } - - void PS2Keyboard::NotifyOwner() - { - if ( !owner) { return; } - owner->OnKeystroke(this, ownerptr); - } - - int PS2Keyboard::DecodeScancode(uint8_t scancode) - { - const uint8_t SCANCODE_ESCAPE = 0xE0; - if ( scancode == SCANCODE_ESCAPE ) - { - scancodeescaped = true; - return 0; - } - - int offset = (scancodeescaped) ? 0x80 : 0; - int kbkey = scancode & 0x7F; - if ( scancode & 0x80 ) { kbkey = -kbkey - offset; } - else { kbkey = kbkey + offset; } - - scancodeescaped = false; - - // kbkey is now in the format specified in . - - return kbkey; - } - - uint8_t PS2Keyboard::PopScancode() - { - return CPU::InPortB(iobase + DATA); - } - - void PS2Keyboard::UpdateLEDs(int ledval) - { - while ( (CPU::InPortB(iobase + STATUS) & (1<<1)) != 0 ) { } - CPU::OutPortB(iobase + COMMAND, CMD_SETLED); - while ( (CPU::InPortB(iobase + STATUS) & (1<<1)) != 0 ) { } - CPU::OutPortB(iobase + COMMAND, ledval); - } - - void PS2Keyboard::SetOwner(KeyboardOwner* owner, void* user) - { - kthread_mutex_lock(&kblock); - this->owner = owner; - this->ownerptr = user; - kthread_mutex_unlock(&kblock); - if ( queueused ) { NotifyOwner(); } - } - - bool PS2Keyboard::PushKey(int key) - { - // Check if we need to allocate or resize the circular queue. - if ( queueused == queuelength ) - { - size_t newqueuelength = (queuelength) ? queuelength * 2 : 32UL; - int* newqueue = new int[newqueuelength]; - if ( !newqueue ) { return false; } - size_t elemsize = sizeof(*queue); - size_t leadingavai = queuelength-queueoffset; - size_t leading = (leadingavai < queueused) ? leadingavai : queueused; - size_t trailing = queueused - leading; - memcpy(newqueue, queue + queueoffset, leading * elemsize); - memcpy(newqueue + leading, queue, trailing * elemsize); - delete[] queue; - queue = newqueue; - queuelength = newqueuelength; - queueoffset = 0; - } - - queue[(queueoffset + queueused++) % queuelength] = key; - return true; - } - - int PS2Keyboard::PopKey() - { - if ( !queueused ) { return 0; } - int kbkey = queue[queueoffset]; - queueoffset = (queueoffset + 1) % queuelength; - queueused--; - return kbkey; - } - - int PS2Keyboard::Read() - { - ScopedLock lock(&kblock); - return PopKey(); - } - - size_t PS2Keyboard::GetPending() const - { - ScopedLock lock(&kblock); - return queueused; - } - - bool PS2Keyboard::HasPending() const - { - ScopedLock lock(&kblock); - return queueused; - } + ((PS2Keyboard*) user)->OnInterrupt(regs); } + +PS2Keyboard::PS2Keyboard(uint16_t iobase, uint8_t interrupt) +{ + this->queue = NULL; + this->queuelength = 0; + this->queueoffset = 0; + this->queueused = 0; + this->owner = NULL; + this->ownerptr = NULL; + this->iobase = iobase; + this->interrupt = interrupt; + this->leds = 0; + this->scancodeescaped = false; + this->kblock = KTHREAD_MUTEX_INITIALIZER; + Interrupt::RegisterHandler(interrupt, PS2Keyboard__OnInterrupt, this); + + // If any scancodes were already pending, our interrupt handler will + // never be called. Let's just discard anything pending. + PopScancode(); +} + +PS2Keyboard::~PS2Keyboard() +{ + Interrupt::RegisterHandler(interrupt, NULL, NULL); + delete[] queue; +} + +struct PS2KeyboardWork +{ + PS2Keyboard* kb; + uint8_t scancode; +}; + +static void PS2Keyboard__InterruptWork(void* payload, size_t size) +{ + assert(size == sizeof(PS2KeyboardWork)); + PS2KeyboardWork* work = (PS2KeyboardWork*) payload; + work->kb->InterruptWork(work->scancode); +} + +void PS2Keyboard::OnInterrupt(CPU::InterruptRegisters* regs) +{ + uint8_t scancode = PopScancode(); + if ( scancode == KBKEY_F10 ) + { + CurrentThread()->SaveRegisters(regs); + Debugger::Run(); + } + PS2KeyboardWork work; + work.kb = this; + work.scancode = scancode; + Interrupt::ScheduleWork(PS2Keyboard__InterruptWork, &work, sizeof(work)); +} + +void PS2Keyboard::InterruptWork(uint8_t scancode) +{ + kthread_mutex_lock(&kblock); + int kbkey = DecodeScancode(scancode); + if ( !kbkey ) + { + kthread_mutex_unlock(&kblock); + return; + } + + if ( !PushKey(kbkey) ) + { + Log::PrintF("Warning: dropping keystroke due to insufficient " + "storage space in PS2 keyboard driver.\n"); + kthread_mutex_unlock(&kblock); + return; + } + + uint8_t newleds = leds; + + if ( kbkey == KBKEY_CAPSLOCK ) + newleds ^= LED_CAPSLCK; + if ( kbkey == KBKEY_SCROLLLOCK ) + newleds ^= LED_SCRLCK; + if ( kbkey == KBKEY_NUMLOCK ) + newleds ^= LED_NUMLCK; + + if ( newleds != leds ) + UpdateLEDs(leds = newleds); + + kthread_mutex_unlock(&kblock); + + NotifyOwner(); +} + +void PS2Keyboard::NotifyOwner() +{ + if ( !owner) + return; + owner->OnKeystroke(this, ownerptr); +} + +int PS2Keyboard::DecodeScancode(uint8_t scancode) +{ + const uint8_t SCANCODE_ESCAPE = 0xE0; + if ( scancode == SCANCODE_ESCAPE ) + { + scancodeescaped = true; + return 0; + } + + int offset = scancodeescaped ? 0x80 : 0; + int kbkey = scancode & 0x7F; + kbkey = scancode & 0x80 ? -kbkey - offset : kbkey + offset; + + scancodeescaped = false; + + // kbkey is now in the format specified in . + + return kbkey; +} + +uint8_t PS2Keyboard::PopScancode() +{ + return CPU::InPortB(iobase + DATA); +} + +void PS2Keyboard::UpdateLEDs(int ledval) +{ + while ( (CPU::InPortB(iobase + STATUS) & (1<<1)) ); + CPU::OutPortB(iobase + COMMAND, CMD_SETLED); + while ( (CPU::InPortB(iobase + STATUS) & (1<<1)) ); + CPU::OutPortB(iobase + COMMAND, ledval); +} + +void PS2Keyboard::SetOwner(KeyboardOwner* owner, void* user) +{ + kthread_mutex_lock(&kblock); + this->owner = owner; + this->ownerptr = user; + kthread_mutex_unlock(&kblock); + if ( queueused ) + NotifyOwner(); +} + +bool PS2Keyboard::PushKey(int key) +{ + // Check if we need to allocate or resize the circular queue. + if ( queueused == queuelength ) + { + size_t newqueuelength = (queuelength) ? queuelength * 2 : 32UL; + int* newqueue = new int[newqueuelength]; + if ( !newqueue ) + return false; + size_t elemsize = sizeof(*queue); + size_t leadingavai = queuelength-queueoffset; + size_t leading = (leadingavai < queueused) ? leadingavai : queueused; + size_t trailing = queueused - leading; + memcpy(newqueue, queue + queueoffset, leading * elemsize); + memcpy(newqueue + leading, queue, trailing * elemsize); + delete[] queue; + queue = newqueue; + queuelength = newqueuelength; + queueoffset = 0; + } + + queue[(queueoffset + queueused++) % queuelength] = key; + return true; +} + +int PS2Keyboard::PopKey() +{ + if ( !queueused ) + return 0; + int kbkey = queue[queueoffset]; + queueoffset = (queueoffset + 1) % queuelength; + queueused--; + return kbkey; +} + +int PS2Keyboard::Read() +{ + ScopedLock lock(&kblock); + return PopKey(); +} + +size_t PS2Keyboard::GetPending() const +{ + ScopedLock lock(&kblock); + return queueused; +} + +bool PS2Keyboard::HasPending() const +{ + ScopedLock lock(&kblock); + return queueused; +} + +} // namespace Sortix diff --git a/kernel/kb/ps2.h b/kernel/kb/ps2.h index b3684729..7ce93e1d 100644 --- a/kernel/kb/ps2.h +++ b/kernel/kb/ps2.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. This file is part of Sortix. @@ -25,47 +25,51 @@ #ifndef SORTIX_KB_PS2_H #define SORTIX_KB_PS2_H +#include +#include + #include #include -namespace Sortix +namespace Sortix { + +class PS2Keyboard : public Keyboard { - class PS2Keyboard : public Keyboard - { - public: - PS2Keyboard(uint16_t iobase, uint8_t interrupt); - virtual ~PS2Keyboard(); - virtual int Read(); - virtual size_t GetPending() const; - virtual bool HasPending() const; - virtual void SetOwner(KeyboardOwner* owner, void* user); +public: + PS2Keyboard(uint16_t iobase, uint8_t interrupt); + virtual ~PS2Keyboard(); + virtual int Read(); + virtual size_t GetPending() const; + virtual bool HasPending() const; + virtual void SetOwner(KeyboardOwner* owner, void* user); - public: - void OnInterrupt(CPU::InterruptRegisters* regs); - void InterruptWork(uint8_t scancode); +public: + void OnInterrupt(CPU::InterruptRegisters* regs); + void InterruptWork(uint8_t scancode); - private: - uint8_t PopScancode(); - int DecodeScancode(uint8_t scancode); - void UpdateLEDs(int ledval); - bool PushKey(int key); - int PopKey(); - void NotifyOwner(); +private: + uint8_t PopScancode(); + int DecodeScancode(uint8_t scancode); + void UpdateLEDs(int ledval); + bool PushKey(int key); + int PopKey(); + void NotifyOwner(); - private: - int* queue; - size_t queuelength; - size_t queueoffset; - size_t queueused; - KeyboardOwner* owner; - void* ownerptr; - uint16_t iobase; - uint8_t interrupt; - bool scancodeescaped; - uint8_t leds; - mutable kthread_mutex_t kblock; +private: + int* queue; + size_t queuelength; + size_t queueoffset; + size_t queueused; + KeyboardOwner* owner; + void* ownerptr; + uint16_t iobase; + uint8_t interrupt; + bool scancodeescaped; + uint8_t leds; + mutable kthread_mutex_t kblock; - }; -} +}; + +} // namespace Sortix #endif