/*
+ * Copyright (c) 2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
#include <string>
-#include "base/trace.hh"
#include "cpu/intr_control.hh"
+#include "debug/IdeCtrl.hh"
#include "dev/ide_ctrl.hh"
#include "dev/ide_disk.hh"
#include "mem/packet.hh"
#include "params/IdeController.hh"
#include "sim/byteswap.hh"
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::string;
// Bus master IDE registers
enum BMIRegOffset {
IdeController::Channel::~Channel()
{
- delete master;
- delete slave;
}
IdeController::IdeController(Params *p)
- : PciDev(p), primary(name() + ".primary", BARSize[0], BARSize[1]),
+ : PciDevice(p), primary(name() + ".primary", BARSize[0], BARSize[1]),
secondary(name() + ".secondary", BARSize[2], BARSize[3]),
bmiAddr(0), bmiSize(BARSize[4]),
primaryTiming(htole(timeRegWithDecodeEn)),
secondaryTiming(htole(timeRegWithDecodeEn)),
deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0),
- ioEnabled(false), bmEnabled(false)
+ ioEnabled(false), bmEnabled(false),
+ ioShift(p->io_shift), ctrlOffset(p->ctrl_offset)
{
if (params()->disks.size() > 3)
panic("IDE controllers support a maximum of 4 devices attached!\n");
}
primary.select(false);
secondary.select(false);
+
+ if ((BARAddrs[0] & ~BAR_IO_MASK) && (!legacyIO[0] || ioShift)) {
+ primary.cmdAddr = BARAddrs[0]; primary.cmdSize = BARSize[0];
+ primary.ctrlAddr = BARAddrs[1]; primary.ctrlSize = BARSize[1];
+ }
+ if ((BARAddrs[2] & ~BAR_IO_MASK) && (!legacyIO[2] || ioShift)) {
+ secondary.cmdAddr = BARAddrs[2]; secondary.cmdSize = BARSize[2];
+ secondary.ctrlAddr = BARAddrs[3]; secondary.ctrlSize = BARSize[3];
+ }
+
+ ioEnabled = (config.command & htole(PCI_CMD_IOSE));
+ bmEnabled = (config.command & htole(PCI_CMD_BME));
}
bool
IdeController::intrPost()
{
primary.bmiRegs.status.intStatus = 1;
- PciDev::intrPost();
+ PciDevice::intrPost();
}
void
{
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset < PCI_DEVICE_SPECIFIC) {
- return PciDev::readConfig(pkt);
+ return PciDevice::readConfig(pkt);
}
- pkt->allocate();
-
switch (pkt->getSize()) {
case sizeof(uint8_t):
switch (offset) {
break;
case sizeof(uint16_t):
switch (offset) {
+ case UDMAControl:
+ pkt->set<uint16_t>(udmaControl);
+ break;
case PrimaryTiming:
pkt->set<uint16_t>(primaryTiming);
break;
(uint32_t)pkt->get<uint16_t>());
break;
case sizeof(uint32_t):
- panic("No 32bit reads implemented for this device.");
+ switch (offset) {
+ case PrimaryTiming:
+ pkt->set<uint32_t>(primaryTiming);
+ break;
+ case IDEConfig:
+ pkt->set<uint32_t>(ideConfig);
+ break;
+ default:
+ panic("No 32bit reads implemented for this device.");
+ }
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset,
(uint32_t)pkt->get<uint32_t>());
break;
{
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::writeConfig(pkt);
+ PciDevice::writeConfig(pkt);
} else {
switch (pkt->getSize()) {
case sizeof(uint8_t):
break;
case sizeof(uint16_t):
switch (offset) {
+ case UDMAControl:
+ udmaControl = pkt->get<uint16_t>();
+ break;
case PrimaryTiming:
primaryTiming = pkt->get<uint16_t>();
break;
offset, (uint32_t)pkt->get<uint16_t>());
break;
case sizeof(uint32_t):
- panic("Write of unimplemented PCI config. register: %x\n", offset);
+ switch (offset) {
+ case PrimaryTiming:
+ primaryTiming = pkt->get<uint32_t>();
+ break;
+ case IDEConfig:
+ ideConfig = pkt->get<uint32_t>();
+ break;
+ default:
+ panic("Write of unimplemented PCI config. register: %x\n", offset);
+ }
break;
default:
panic("invalid access size(?) for PCI configspace!\n");
break;
case PCI_COMMAND:
+ DPRINTF(IdeCtrl, "Writing to PCI Command val: %#x\n", config.command);
ioEnabled = (config.command & htole(PCI_CMD_IOSE));
bmEnabled = (config.command & htole(PCI_CMD_BME));
break;
newVal.active = oldVal.active;
// to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
- if (oldVal.intStatus && newVal.intStatus)
+ if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) {
newVal.intStatus = 0; // clear the interrupt?
- else
- newVal.intStatus = oldVal.intStatus;
- if (oldVal.dmaError && newVal.dmaError)
+ } else {
+ // Assigning two bitunion fields to each other does not
+ // work as intended, so we need to use this temporary variable
+ // to get around the bug.
+ uint8_t tmp = oldVal.intStatus;
+ newVal.intStatus = tmp;
+ }
+ if ((oldVal.dmaError == 1) && (newVal.dmaError == 1)) {
newVal.dmaError = 0;
- else
- newVal.dmaError = oldVal.dmaError;
+ } else {
+ uint8_t tmp = oldVal.dmaError;
+ newVal.dmaError = tmp;
+ }
bmiRegs.status = newVal;
}
void
IdeController::dispatchAccess(PacketPtr pkt, bool read)
{
- pkt->allocate();
if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
panic("Bad IDE read size: %d\n", pkt->getSize());
if (addr >= primary.cmdAddr &&
addr < (primary.cmdAddr + primary.cmdSize)) {
addr -= primary.cmdAddr;
+ // linux may have shifted the address by ioShift,
+ // here we shift it back, similarly for ctrlOffset.
+ addr >>= ioShift;
primary.accessCommand(addr, size, dataPtr, read);
} else if (addr >= primary.ctrlAddr &&
addr < (primary.ctrlAddr + primary.ctrlSize)) {
addr -= primary.ctrlAddr;
+ addr += ctrlOffset;
primary.accessControl(addr, size, dataPtr, read);
} else if (addr >= secondary.cmdAddr &&
addr < (secondary.cmdAddr + secondary.cmdSize)) {
panic("IDE controller access to invalid address: %#x\n", addr);
}
+#ifndef NDEBUG
uint32_t data;
if (pkt->getSize() == 1)
data = pkt->get<uint8_t>();
data = pkt->get<uint32_t>();
DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n",
read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data);
+#endif
pkt->makeAtomicResponse();
}
}
void
-IdeController::serialize(std::ostream &os)
+IdeController::serialize(CheckpointOut &cp) const
{
- // Serialize the PciDev base class
- PciDev::serialize(os);
+ // Serialize the PciDevice base class
+ PciDevice::serialize(cp);
// Serialize channels
- primary.serialize("primary", os);
- secondary.serialize("secondary", os);
+ primary.serialize("primary", cp);
+ secondary.serialize("secondary", cp);
// Serialize config registers
SERIALIZE_SCALAR(primaryTiming);
}
void
-IdeController::Channel::serialize(const std::string &base, std::ostream &os)
+IdeController::Channel::serialize(const std::string &base,
+ CheckpointOut &cp) const
{
- paramOut(os, base + ".cmdAddr", cmdAddr);
- paramOut(os, base + ".cmdSize", cmdSize);
- paramOut(os, base + ".ctrlAddr", ctrlAddr);
- paramOut(os, base + ".ctrlSize", ctrlSize);
+ paramOut(cp, base + ".cmdAddr", cmdAddr);
+ paramOut(cp, base + ".cmdSize", cmdSize);
+ paramOut(cp, base + ".ctrlAddr", ctrlAddr);
+ paramOut(cp, base + ".ctrlSize", ctrlSize);
uint8_t command = bmiRegs.command;
- paramOut(os, base + ".bmiRegs.command", command);
- paramOut(os, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
+ paramOut(cp, base + ".bmiRegs.command", command);
+ paramOut(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
uint8_t status = bmiRegs.status;
- paramOut(os, base + ".bmiRegs.status", status);
- paramOut(os, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
- paramOut(os, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
- paramOut(os, base + ".selectBit", selectBit);
+ paramOut(cp, base + ".bmiRegs.status", status);
+ paramOut(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
+ paramOut(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
+ paramOut(cp, base + ".selectBit", selectBit);
}
void
-IdeController::unserialize(Checkpoint *cp, const std::string §ion)
+IdeController::unserialize(CheckpointIn &cp)
{
- // Unserialize the PciDev base class
- PciDev::unserialize(cp, section);
+ // Unserialize the PciDevice base class
+ PciDevice::unserialize(cp);
// Unserialize channels
- primary.unserialize("primary", cp, section);
- secondary.unserialize("secondary", cp, section);
+ primary.unserialize("primary", cp);
+ secondary.unserialize("secondary", cp);
// Unserialize config registers
UNSERIALIZE_SCALAR(primaryTiming);
}
void
-IdeController::Channel::unserialize(const std::string &base, Checkpoint *cp,
- const std::string §ion)
+IdeController::Channel::unserialize(const std::string &base, CheckpointIn &cp)
{
- paramIn(cp, section, base + ".cmdAddr", cmdAddr);
- paramIn(cp, section, base + ".cmdSize", cmdSize);
- paramIn(cp, section, base + ".ctrlAddr", ctrlAddr);
- paramIn(cp, section, base + ".ctrlSize", ctrlSize);
+ paramIn(cp, base + ".cmdAddr", cmdAddr);
+ paramIn(cp, base + ".cmdSize", cmdSize);
+ paramIn(cp, base + ".ctrlAddr", ctrlAddr);
+ paramIn(cp, base + ".ctrlSize", ctrlSize);
uint8_t command;
- paramIn(cp, section, base +".bmiRegs.command", command);
+ paramIn(cp, base +".bmiRegs.command", command);
bmiRegs.command = command;
- paramIn(cp, section, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
+ paramIn(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
uint8_t status;
- paramIn(cp, section, base + ".bmiRegs.status", status);
+ paramIn(cp, base + ".bmiRegs.status", status);
bmiRegs.status = status;
- paramIn(cp, section, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
- paramIn(cp, section, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
- paramIn(cp, section, base + ".selectBit", selectBit);
+ paramIn(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
+ paramIn(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
+ paramIn(cp, base + ".selectBit", selectBit);
select(selectBit);
}