From 7eb991b9ff4c607f5e10536046e315b3cd9ec42e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 26 Oct 2020 17:59:38 -0700 Subject: [PATCH] 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 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/36815 Reviewed-by: Matthew Poremba Maintainer: Gabe Black Tested-by: kokoro --- src/dev/x86/i8237.cc | 193 ++++++++++++++++++++++++------------------- src/dev/x86/i8237.hh | 52 +++++++++++- 2 files changed, 161 insertions(+), 84 deletions(-) diff --git a/src/dev/x86/i8237.cc b/src/dev/x86/i8237.cc index 05d08c862..a7f641fe0 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" +namespace X86ISA +{ + +namespace +{ + +I8237::Register::ReadFunc +readUnimpl(const std::string &label) +{ + return [label](I8237::Register ®) -> uint8_t { + panic("Read from i8237 %s unimplemented.", label); + }; +} + +I8237::Register::WriteFunc +writeUnimpl(const std::string &label) +{ + return [label](I8237::Register ®, 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 ®) -> 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 ®, 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 -X86ISA::I8237::read(PacketPtr pkt) +I8237::read(PacketPtr pkt) { - 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); - } + regs.read(pkt->getAddr(), pkt->getPtr(), 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 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(), 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 d5044d648..61544855b 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 + #include "dev/io_device.hh" +#include "dev/reg_bank.hh" #include "params/I8237.hh" namespace X86ISA @@ -37,10 +40,57 @@ namespace X86ISA 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 channels; + + Register statusCommandReg; + WriteOnlyReg requestReg; + WriteOnlyReg setMaskBitReg; + WriteOnlyReg modeReg; + WriteOnlyReg clearFlipFlopReg; + Register temporaryMasterClearReg; + WriteOnlyReg clearMaskReg; + WriteOnlyReg writeMaskReg; + + void setMaskBit(Register ®, const uint8_t &command); + public: typedef I8237Params Params; @@ -50,7 +100,7 @@ class I8237 : public BasicPioDevice return dynamic_cast(_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; -- 2.30.2