Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/36815 )

Change subject: dev: Convert the x86 i8237 DMA controller to use RegBank.
......................................................................

dev: Convert the x86 i8237 DMA controller to use RegBank.

This gets rid of the requirement to only modify one byte register at a
time, and builds some structure around individual DMA channels.

The one small feature of the i8237 that was implemented is still
implemented, but now with a method of the i8237.

Change-Id: Ibc2b2d75f2a3b860da3f28ae649c6f1a099bdf7d
---
M src/dev/x86/i8237.cc
M src/dev/x86/i8237.hh
2 files changed, 162 insertions(+), 85 deletions(-)



diff --git a/src/dev/x86/i8237.cc b/src/dev/x86/i8237.cc
index 05d08c8..a7f641f 100644
--- a/src/dev/x86/i8237.cc
+++ b/src/dev/x86/i8237.cc
@@ -28,110 +28,137 @@

 #include "dev/x86/i8237.hh"

+#include "base/cprintf.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"

-Tick
-X86ISA::I8237::read(PacketPtr pkt)
+namespace X86ISA
 {
-    assert(pkt->getSize() == 1);
-    Addr offset = pkt->getAddr() - pioAddr;
-    switch (offset) {
-      case 0x0:
- panic("Read from i8237 channel 0 current address unimplemented.\n");
-      case 0x1:
-        panic("Read from i8237 channel 0 remaining "
-                "word count unimplemented.\n");
-      case 0x2:
- panic("Read from i8237 channel 1 current address unimplemented.\n");
-      case 0x3:
-        panic("Read from i8237 channel 1 remaining "
-                "word count unimplemented.\n");
-      case 0x4:
- panic("Read from i8237 channel 2 current address unimplemented.\n");
-      case 0x5:
-        panic("Read from i8237 channel 2 remaining "
-                "word count unimplemented.\n");
-      case 0x6:
- panic("Read from i8237 channel 3 current address unimplemented.\n");
-      case 0x7:
-        panic("Read from i8237 channel 3 remaining "
-                "word count unimplemented.\n");
-      case 0x8:
-        panic("Read from i8237 status register unimplemented.\n");
-      default:
-        panic("Read from undefined i8237 register %d.\n", offset);
-    }
+
+namespace
+{
+
+I8237::Register::ReadFunc
+readUnimpl(const std::string &label)
+{
+    return [label](I8237::Register &reg) -> uint8_t {
+        panic("Read from i8237 %s unimplemented.", label);
+    };
+}
+
+I8237::Register::WriteFunc
+writeUnimpl(const std::string &label)
+{
+    return [label](I8237::Register &reg, const uint8_t &value) {
+        panic("Write to i8237 %s unimplemented.", label);
+    };
+}
+
+} // anonymous namespace
+
+I8237::Channel::ChannelAddrReg::ChannelAddrReg(Channel &channel) :
+    Register(csprintf("channel %d current address", channel.number))
+{
+    reader(readUnimpl(name()));
+    writer(writeUnimpl(name()));
+}
+
+I8237::Channel::ChannelRemainingReg::ChannelRemainingReg(Channel &channel) :
+    Register(csprintf("channel %d remaining word count", channel.number))
+{
+    reader(readUnimpl(name()));
+    writer(writeUnimpl(name()));
+}
+
+I8237::WriteOnlyReg::WriteOnlyReg(const std::string &new_name, Addr offset) :
+    Register(new_name)
+{
+    reader([offset](I8237::Register &reg) -> uint8_t {
+        panic("Illegal read from i8237 register %d.", offset);
+    });
+}
+
+I8237::I8237(const Params &p) : BasicPioDevice(p, 16), latency(p.pio_latency),
+    regs("registers", pioAddr), channels{{{0}, {1}, {2}, {3}}},
+    statusCommandReg("status/command"),
+    requestReg("request", 0x9),
+    setMaskBitReg("set mask bit", 0xa),
+    modeReg("mode", 0xb),
+    clearFlipFlopReg("clear flip-flop", 0xc),
+    temporaryMasterClearReg("temporary/maskter clear"),
+    clearMaskReg("clear mask", 0xe),
+    writeMaskReg("write mask", 0xf)
+{
+    // Add the channel address and remaining registers.
+    for (auto &channel: channels)
+        regs.addRegisters({ channel.addrReg, channel.remainingReg });
+
+    // Add the other registers individually.
+    regs.addRegisters({
+        statusCommandReg.
+            reader(readUnimpl("status register")).
+            writer(writeUnimpl("command register")),
+
+        requestReg.
+            writer(writeUnimpl("request register")),
+
+        setMaskBitReg.
+            writer(this, &I8237::setMaskBit),
+
+        modeReg.
+            writer(writeUnimpl("mode register")),
+
+        clearFlipFlopReg.
+            writer(writeUnimpl("clear LSB/MSB flip-flop register")),
+
+        temporaryMasterClearReg.
+            reader(readUnimpl("temporary register")).
+            writer(writeUnimpl("master clear register")),
+
+        clearMaskReg.
+            writer(writeUnimpl("clear mask register")),
+
+        writeMaskReg.
+            writer(writeUnimpl("write all mask register bits"))
+    });
+}
+
+void
+I8237::setMaskBit(Register &reg, const uint8_t &command)
+{
+    uint8_t select = bits(command, 1, 0);
+    uint8_t bitVal = bits(command, 2);
+    if (!bitVal)
+        panic("Turning on i8237 channels unimplemented.");
+    replaceBits(maskReg, select, bitVal);
+}
+
+Tick
+I8237::read(PacketPtr pkt)
+{
+    regs.read(pkt->getAddr(), pkt->getPtr<void>(), pkt->getSize());
     pkt->makeAtomicResponse();
     return latency;
 }

 Tick
-X86ISA::I8237::write(PacketPtr pkt)
+I8237::write(PacketPtr pkt)
 {
-    assert(pkt->getSize() == 1);
-    Addr offset = pkt->getAddr() - pioAddr;
-    switch (offset) {
-      case 0x0:
- panic("Write to i8237 channel 0 starting address unimplemented.\n");
-      case 0x1:
-        panic("Write to i8237 channel 0 starting "
-                "word count unimplemented.\n");
-      case 0x2:
- panic("Write to i8237 channel 1 starting address unimplemented.\n");
-      case 0x3:
-        panic("Write to i8237 channel 1 starting "
-                "word count unimplemented.\n");
-      case 0x4:
- panic("Write to i8237 channel 2 starting address unimplemented.\n");
-      case 0x5:
-        panic("Write to i8237 channel 2 starting "
-                "word count unimplemented.\n");
-      case 0x6:
- panic("Write to i8237 channel 3 starting address unimplemented.\n");
-      case 0x7:
-        panic("Write to i8237 channel 3 starting "
-                "word count unimplemented.\n");
-      case 0x8:
-        panic("Write to i8237 command register unimplemented.\n");
-      case 0x9:
-        panic("Write to i8237 request register unimplemented.\n");
-      case 0xa:
-        {
-            uint8_t command = pkt->getLE<uint8_t>();
-            uint8_t select = bits(command, 1, 0);
-            uint8_t bitVal = bits(command, 2);
-            if (!bitVal)
-                panic("Turning on i8237 channels unimplemented.\n");
-            replaceBits(maskReg, select, bitVal);
-        }
-        break;
-      case 0xb:
-        panic("Write to i8237 mode register unimplemented.\n");
-      case 0xc:
-        panic("Write to i8237 clear LSB/MSB flip-flop "
-                "register unimplemented.\n");
-      case 0xd:
- panic("Write to i8237 master clear/reset register unimplemented.\n");
-      case 0xe:
-        panic("Write to i8237 clear mask register unimplemented.\n");
-      case 0xf:
- panic("Write to i8237 write all mask register bits unimplemented.\n");
-      default:
-        panic("Write to undefined i8237 register.\n");
-    }
+    regs.write(pkt->getAddr(), pkt->getPtr<void>(), pkt->getSize());
     pkt->makeAtomicResponse();
     return latency;
 }

 void
-X86ISA::I8237::serialize(CheckpointOut &cp) const
+I8237::serialize(CheckpointOut &cp) const
 {
     SERIALIZE_SCALAR(maskReg);
 }

 void
-X86ISA::I8237::unserialize(CheckpointIn &cp)
+I8237::unserialize(CheckpointIn &cp)
 {
     UNSERIALIZE_SCALAR(maskReg);
 }
+
+} // namespace X86ISA
diff --git a/src/dev/x86/i8237.hh b/src/dev/x86/i8237.hh
index d5044d6..6154485 100644
--- a/src/dev/x86/i8237.hh
+++ b/src/dev/x86/i8237.hh
@@ -29,7 +29,10 @@
 #ifndef __DEV_X86_I8237_HH__
 #define __DEV_X86_I8237_HH__

+#include <array>
+
 #include "dev/io_device.hh"
+#include "dev/reg_bank.hh"
 #include "params/I8237.hh"

 namespace X86ISA
@@ -37,10 +40,57 @@

 class I8237 : public BasicPioDevice
 {
+  public:
+    using Register = RegisterBankLE::Register8;
+
   protected:
     Tick latency;
     uint8_t maskReg = 0;

+    RegisterBankLE regs;
+
+    struct Channel
+    {
+        class ChannelAddrReg : public Register
+        {
+          public:
+            ChannelAddrReg(Channel &);
+        };
+
+        class ChannelRemainingReg : public Register
+        {
+          public:
+            ChannelRemainingReg(Channel &);
+        };
+
+        int number;
+
+        ChannelAddrReg addrReg;
+        ChannelRemainingReg remainingReg;
+
+ Channel(int _num) : number(_num), addrReg(*this), remainingReg(*this)
+        {}
+    };
+
+    class WriteOnlyReg : public Register
+    {
+      public:
+        WriteOnlyReg(const std::string &new_name, Addr offset);
+    };
+
+    std::array<Channel, 4> channels;
+
+    Register statusCommandReg;
+    WriteOnlyReg requestReg;
+    WriteOnlyReg setMaskBitReg;
+    WriteOnlyReg modeReg;
+    WriteOnlyReg clearFlipFlopReg;
+    Register temporaryMasterClearReg;
+    WriteOnlyReg clearMaskReg;
+    WriteOnlyReg writeMaskReg;
+
+    void setMaskBit(Register &reg, const uint8_t &command);
+
   public:
     typedef I8237Params Params;

@@ -50,7 +100,7 @@
         return dynamic_cast<const Params &>(_params);
     }

- I8237(const Params &p) : BasicPioDevice(p, 16), latency(p.pio_latency) {}
+    I8237(const Params &p);

     Tick read(PacketPtr pkt) override;
     Tick write(PacketPtr pkt) override;

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/36815
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ibc2b2d75f2a3b860da3f28ae649c6f1a099bdf7d
Gerrit-Change-Number: 36815
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to