From 88d4a8e6ffdbbe94e1db1f8fc5a2b5f7787adc50 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 12 Nov 2010 08:08:36 -0600 Subject: [PATCH] Introduce the notion of a Plug A plug stores a pointer to another device. A plug can store a pointer to a base class or it can store a pointer to a specific device type. In the case of the i8042, the controller only supports two types of devices and the devices must occur on a specific port. Besides providing for better marshalling support, a plug has NULL pointer dereferencing checks built into it. For the i8042, I need to update the code to work properly with empty plugs. Plugs need to be part of the factory interface. So far we've been dealing with non-optional devices that are constructed purely by composition. Now that we have optional devices, we need a generic way to instantiate the optional devices and to attach them to the appropriate devices. --- include/i8042.hpp | 7 ++++--- include/plug.hpp | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/util.hpp | 7 +++++++ pc/i8042.cpp | 24 ++++++++++----------- 4 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 include/plug.hpp diff --git a/include/i8042.hpp b/include/i8042.hpp index 240f936..c7a97b9 100644 --- a/include/i8042.hpp +++ b/include/i8042.hpp @@ -1,8 +1,9 @@ #ifndef I8042_HPP #define I8042_HPP -#include "ps2.hpp" #include "ps2_keyboard.hpp" +#include "ps2_mouse.hpp" +#include "plug.hpp" class I8042 { @@ -30,8 +31,8 @@ private: /* Bitmask of devices with data available. */ uint8_t pending; - PS2Keyboard *port0; - PS2Device *port1; + Plug kbd; + Plug aux; OutputPin irq_kbd; OutputPin irq_mouse; diff --git a/include/plug.hpp b/include/plug.hpp new file mode 100644 index 0000000..2982e13 --- /dev/null +++ b/include/plug.hpp @@ -0,0 +1,62 @@ +#ifndef PLUG_HPP +#define PLUG_HPP + +#include + +#include "marshal.hpp" + +class NullPointer : public std::exception +{ +}; + +template +class Plug +{ +public: + void plug(T *ptr) { + this->ptr = ptr; + } + + void unplug(void) { + this->ptr = NULL; + } + + bool empty(void) const { + return (this->ptr == NULL); + } + + T &operator*(void) const { + return *(this->get()); + } + + T *operator->(void) const { + return this->get(); + } + + T *get(void) const { + if (this->ptr == NULL) { + throw new NullPointer(); + } + return this->ptr; + } + +private: + T *ptr; +}; + +template +void marshal(Marshaller *m, const char *name, Plug *plug) +{ + bool empty; + + m->start_struct(name, "Plug"); + empty = plug->empty(); + marshal(m, "empty", &empty); + if (!empty) { + marshal(m, NULL, plug->get()); + } + m->end_struct(); + +} + +#endif diff --git a/include/util.hpp b/include/util.hpp index 4657431..7d40834 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -15,6 +15,13 @@ template class Array { public: + const T &at(size_t index) const { + if (index < 0 || index >= N) { + throw new OutOfBounds(); + } + return this->data[index]; + } + T &at(size_t index) { if (index < 0 || index >= N) { throw new OutOfBounds(); diff --git a/pc/i8042.cpp b/pc/i8042.cpp index 4544c9f..7a66b34 100644 --- a/pc/i8042.cpp +++ b/pc/i8042.cpp @@ -94,9 +94,9 @@ uint32_t I8042::read_status(uint32_t addr) void I8042::queue(int b, int aux) { if (aux) { - this->port1->queue(b); + this->aux->queue(b); } else { - this->port0->queue(b); + this->kbd->queue(b); } } @@ -198,9 +198,9 @@ uint32_t I8042::read_data(uint32_t addr) uint32_t val; if (this->pending == KBD_PENDING_AUX) - val = this->port1->read(); + val = this->aux->read(); else - val = this->port0->read(); + val = this->kbd->read(); return val; } @@ -209,11 +209,11 @@ void I8042::write_data(uint32_t addr, uint32_t val) { switch(this->write_cmd) { case 0: - this->port0->write(val); + this->kbd->write(val); break; case KBD_CCMD_WRITE_MODE: this->mode = val; - this->port0->set_translation((this->mode & KBD_MODE_KCC) != 0); + this->kbd->set_translation((this->mode & KBD_MODE_KCC) != 0); /* ??? */ this->update_irq(); break; @@ -227,7 +227,7 @@ void I8042::write_data(uint32_t addr, uint32_t val) this->ioport92_write(0, val); break; case KBD_CCMD_WRITE_MOUSE: - this->port1->write(val); + this->aux->write(val); break; default: break; @@ -240,8 +240,8 @@ void I8042::reset(void) this->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; this->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED; this->outport = KBD_OUT_RESET | KBD_OUT_A20; - this->port0->reset(); - this->port1->reset(); + this->kbd->reset(); + this->aux->reset(); } void I8042::pickle(Marshaller *m, const char *name) @@ -252,10 +252,8 @@ void I8042::pickle(Marshaller *m, const char *name) marshal(m, "mode", &this->mode); marshal(m, "outport", &this->outport); marshal(m, "pending", &this->pending); - m->start_array("port"); - marshal(m, NULL, this->port0); - marshal(m, NULL, this->port1); - m->end_array(); + marshal(m, "kbd", &this->kbd); + marshal(m, "aux", &this->aux); marshal(m, "irq_kbd", &this->irq_kbd); marshal(m, "irq_mouse", &this->irq_mouse); marshal(m, "a20_line", &this->a20_line); -- 2.11.4.GIT