#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<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
#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
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 ®, const uint8_t &command);
+
public:
typedef I8237Params Params;
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;