50 #include "debug/IdeCtrl.hh"
54 #include "params/IdeController.hh"
80 IdeController::Channel::Channel(
81 string newName,
Addr _cmdSize,
Addr _ctrlSize) :
83 cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize),
84 master(NULL), slave(NULL), selected(NULL)
86 memset(&bmiRegs, 0,
sizeof(bmiRegs));
87 bmiRegs.status.dmaCap0 = 1;
88 bmiRegs.status.dmaCap1 = 1;
91 IdeController::Channel::~Channel()
96 :
PciDevice(p), primary(
name() +
".primary", BARSize[0], BARSize[1]),
97 secondary(
name() +
".secondary", BARSize[2], BARSize[3]),
98 bmiAddr(0), bmiSize(BARSize[4]),
101 deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0),
102 ioEnabled(false), bmEnabled(false),
103 ioShift(p->io_shift), ctrlOffset(p->ctrl_offset)
105 if (
params()->disks.size() > 3)
106 panic(
"IDE controllers support a maximum of 4 devices attached!\n");
109 int numDisks =
params()->disks.size();
119 for (
int i = 0;
i <
params()->disks.size();
i++) {
120 params()->disks[
i]->setController(
this);
147 primary.bmiRegs.status.intStatus = 1;
160 panic(
"Unable to find disk based on pointer %#x\n", disk);
163 channel->bmiRegs.command.startStop = 0;
164 channel->bmiRegs.status.active = 0;
165 channel->bmiRegs.status.intStatus = 1;
177 case sizeof(uint8_t):
198 panic(
"Invalid PCI configuration read for size 1 at offset: %#x!\n",
201 DPRINTF(IdeCtrl,
"PCI read offset: %#x size: 1 data: %#x\n", offset,
202 (uint32_t)pkt->
get<uint8_t>());
204 case sizeof(uint16_t):
222 panic(
"Invalid PCI configuration read for size 2 offset: %#x!\n",
225 DPRINTF(IdeCtrl,
"PCI read offset: %#x size: 2 data: %#x\n", offset,
226 (uint32_t)pkt->
get<uint16_t>());
228 case sizeof(uint32_t):
237 panic(
"No 32bit reads implemented for this device.");
239 DPRINTF(IdeCtrl,
"PCI read offset: %#x size: 4 data: %#x\n", offset,
240 (uint32_t)pkt->
get<uint32_t>());
243 panic(
"invalid access size(?) for PCI configspace!\n");
258 case sizeof(uint8_t):
273 panic(
"Invalid PCI configuration write "
274 "for size 1 offset: %#x!\n", offset);
276 DPRINTF(IdeCtrl,
"PCI write offset: %#x size: 1 data: %#x\n",
277 offset, (uint32_t)pkt->
get<uint8_t>());
279 case sizeof(uint16_t):
297 panic(
"Invalid PCI configuration write "
298 "for size 2 offset: %#x!\n",
301 DPRINTF(IdeCtrl,
"PCI write offset: %#x size: 2 data: %#x\n",
302 offset, (uint32_t)pkt->
get<uint16_t>());
304 case sizeof(uint32_t):
313 panic(
"Write of unimplemented PCI config. register: %x\n", offset);
317 panic(
"invalid access size(?) for PCI configspace!\n");
360 IdeController::Channel::accessCommand(
Addr offset,
363 const Addr SelectOffset = 6;
364 const uint8_t SelectDevBit = 0x10;
366 if (!read && offset == SelectOffset)
367 select(*data & SelectDevBit);
369 if (selected == NULL) {
370 assert(size ==
sizeof(uint8_t));
373 selected->readCommand(offset, size, data);
375 selected->writeCommand(offset, size, data);
380 IdeController::Channel::accessControl(
Addr offset,
381 int size, uint8_t *data,
bool read)
383 if (selected == NULL) {
384 assert(size ==
sizeof(uint8_t));
387 selected->readControl(offset, size, data);
389 selected->writeControl(offset, size, data);
394 IdeController::Channel::accessBMI(
Addr offset,
395 int size, uint8_t *data,
bool read)
397 assert(offset + size <=
sizeof(BMIRegs));
399 memcpy(data, (uint8_t *)&bmiRegs + offset, size);
404 if (size !=
sizeof(uint8_t))
405 panic(
"Invalid BMIC write size: %x\n", size);
407 BMICommandReg oldVal = bmiRegs.command;
408 BMICommandReg newVal = *
data;
411 if (oldVal.startStop && oldVal.rw != newVal.rw)
412 oldVal.rw = newVal.rw;
414 if (oldVal.startStop != newVal.startStop) {
415 if (selected == NULL)
416 panic(
"DMA start for disk which does not exist\n");
418 if (oldVal.startStop) {
419 DPRINTF(IdeCtrl,
"Stopping DMA transfer\n");
420 bmiRegs.status.active = 0;
422 selected->abortDma();
424 DPRINTF(IdeCtrl,
"Starting DMA transfer\n");
425 bmiRegs.status.active = 1;
427 selected->startDma(
letoh(bmiRegs.bmidtp));
431 bmiRegs.command = newVal;
436 if (size !=
sizeof(uint8_t))
437 panic(
"Invalid BMIS write size: %x\n", size);
439 BMIStatusReg oldVal = bmiRegs.status;
440 BMIStatusReg newVal = *
data;
443 newVal.active = oldVal.active;
446 if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) {
447 newVal.intStatus = 0;
452 uint8_t tmp = oldVal.intStatus;
453 newVal.intStatus = tmp;
455 if ((oldVal.dmaError == 1) && (newVal.dmaError == 1)) {
458 uint8_t tmp = oldVal.dmaError;
459 newVal.dmaError = tmp;
462 bmiRegs.status = newVal;
466 if (size !=
sizeof(uint32_t))
467 panic(
"Invalid BMIDTP write size: %x\n", size);
468 bmiRegs.bmidtp =
htole(*(uint32_t *)data & ~0x3);
471 if (size !=
sizeof(uint8_t) && size !=
sizeof(uint16_t) &&
472 size !=
sizeof(uint32_t))
473 panic(
"IDE controller write of invalid write size: %x\n", size);
474 memcpy((uint8_t *)&bmiRegs + offset, data, size);
487 DPRINTF(IdeCtrl,
"io not enabled\n");
493 uint8_t *dataPtr = pkt->
getPtr<uint8_t>();
501 primary.accessCommand(addr, size, dataPtr, read);
502 }
else if (addr >=
primary.ctrlAddr &&
506 primary.accessControl(addr, size, dataPtr, read);
510 secondary.accessCommand(addr, size, dataPtr, read);
514 secondary.accessControl(addr, size, dataPtr, read);
519 if (addr <
sizeof(Channel::BMIRegs)) {
520 primary.accessBMI(addr, size, dataPtr, read);
522 addr -=
sizeof(Channel::BMIRegs);
523 secondary.accessBMI(addr, size, dataPtr, read);
526 panic(
"IDE controller access to invalid address: %#x\n", addr);
532 data = pkt->
get<uint8_t>();
534 data = pkt->
get<uint16_t>();
536 data = pkt->
get<uint32_t>();
537 DPRINTF(IdeCtrl,
"%s from offset: %#x size: %#x data: %#x\n",
565 primary.serialize(
"primary", cp);
587 paramOut(cp, base +
".cmdAddr", cmdAddr);
588 paramOut(cp, base +
".cmdSize", cmdSize);
589 paramOut(cp, base +
".ctrlAddr", ctrlAddr);
590 paramOut(cp, base +
".ctrlSize", ctrlSize);
591 uint8_t command = bmiRegs.command;
592 paramOut(cp, base +
".bmiRegs.command", command);
593 paramOut(cp, base +
".bmiRegs.reserved0", bmiRegs.reserved0);
594 uint8_t
status = bmiRegs.status;
595 paramOut(cp, base +
".bmiRegs.status", status);
596 paramOut(cp, base +
".bmiRegs.reserved1", bmiRegs.reserved1);
597 paramOut(cp, base +
".bmiRegs.bmidtp", bmiRegs.bmidtp);
598 paramOut(cp, base +
".selectBit", selectBit);
608 primary.unserialize(
"primary", cp);
629 paramIn(cp, base +
".cmdAddr", cmdAddr);
630 paramIn(cp, base +
".cmdSize", cmdSize);
631 paramIn(cp, base +
".ctrlAddr", ctrlAddr);
632 paramIn(cp, base +
".ctrlSize", ctrlSize);
634 paramIn(cp, base +
".bmiRegs.command", command);
635 bmiRegs.command = command;
636 paramIn(cp, base +
".bmiRegs.reserved0", bmiRegs.reserved0);
638 paramIn(cp, base +
".bmiRegs.status", status);
640 paramIn(cp, base +
".bmiRegs.reserved1", bmiRegs.reserved1);
641 paramIn(cp, base +
".bmiRegs.bmidtp", bmiRegs.bmidtp);
642 paramIn(cp, base +
".selectBit", selectBit);
647 IdeControllerParams::create()
Tick readConfig(PacketPtr pkt) override
Read from the PCI config space data that is stored locally.
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
const std::string & name()
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
PCI device, base implementation is only config space.
bool isDiskSelected(IdeDisk *diskPtr)
See if a disk is selected based on its pointer.
Device model for an IDE disk.
Device model for an Intel PIIX4 IDE controller.
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
const Params * params() const
Simple PCI IDE controller with bus mastering capability and UDMA modeled after controller in the Inte...
T * getPtr()
get a pointer to the data ptr.
uint16_t primaryTiming
Registers used in device specific PCI configuration.
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
void dispatchAccess(PacketPtr pkt, bool read)
#define UNSERIALIZE_SCALAR(scalar)
bool legacyIO[6]
Whether the BARs are really hardwired legacy IO locations.
void makeAtomicResponse()
uint64_t Tick
Tick count type.
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
void replaceBits(T &val, int first, int last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
#define PCI_DEVICE_SPECIFIC
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Addr BARAddrs[6]
The current address mapping of the BARs.
#define SERIALIZE_SCALAR(scalar)
Addr bmiAddr
Bus master interface (BMI) registers.
Declaration of the Packet class.
std::ostream CheckpointOut
static const uint16_t timeRegWithDecodeEn
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
void serialize(CheckpointOut &cp) const override
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
void unserialize(CheckpointIn &cp) override
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
PCIConfig config
The current config space.
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
void setDmaComplete(IdeDisk *disk)
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
uint32_t BARSize[6]
The size of the BARs.