X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fide_disk.cc;h=83faf508eeec477f53dd04764d737a77cc0fdc7f;hb=7daed385bf9de7761128eedd5a2995692bdfeb19;hp=5d3346b1ee7868ac4b7618b44169ec8d2887421e;hpb=27d60c27fa4cdbe471463fbf8224950d36456592;p=gem5.git diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 5d3346b1e..83faf508e 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -38,31 +38,27 @@ #include #include +#include "arch/isa_traits.hh" #include "base/chunk_generator.hh" #include "base/cprintf.hh" // csprintf #include "base/trace.hh" #include "dev/disk_image.hh" -#include "dev/ide_disk.hh" #include "dev/ide_ctrl.hh" -#include "dev/tsunami.hh" -#include "dev/tsunami_pchip.hh" -#include "sim/builder.hh" +#include "dev/ide_disk.hh" +#include "sim/core.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" -#include "arch/isa_traits.hh" using namespace std; using namespace TheISA; -IdeDisk::IdeDisk(const string &name, DiskImage *img, - int id, Tick delay) - : SimObject(name), ctrl(NULL), image(img), diskDelay(delay), +IdeDisk::IdeDisk(const Params *p) + : SimObject(p), ctrl(NULL), image(p->image), diskDelay(p->delay), dmaTransferEvent(this), dmaReadCG(NULL), dmaReadWaitEvent(this), dmaWriteCG(NULL), dmaWriteWaitEvent(this), dmaPrdReadEvent(this), dmaReadEvent(this), dmaWriteEvent(this) { // Reset the device state - reset(id); + reset(p->driveID); // fill out the drive ID structure memset(&driveID, 0, sizeof(struct ataparams)); @@ -181,7 +177,7 @@ Addr IdeDisk::pciToDma(Addr pciAddr) { if (ctrl) - return ctrl->plat->pciToDma(pciAddr); + return ctrl->pciToDma(pciAddr); else panic("Access to unset controller!\n"); } @@ -191,120 +187,127 @@ IdeDisk::pciToDma(Addr pciAddr) //// void -IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data) +IdeDisk::readCommand(const Addr offset, int size, uint8_t *data) { - DevAction_t action = ACT_NONE; - - switch (reg_type) { - case COMMAND_BLOCK: - switch (offset) { - // Data transfers occur two bytes at a time - case DATA_OFFSET: - *(uint16_t*)data = cmdReg.data; - action = ACT_DATA_READ_SHORT; - break; - case ERROR_OFFSET: - *data = cmdReg.error; - break; - case NSECTOR_OFFSET: - *data = cmdReg.sec_count; - break; - case SECTOR_OFFSET: - *data = cmdReg.sec_num; - break; - case LCYL_OFFSET: - *data = cmdReg.cyl_low; - break; - case HCYL_OFFSET: - *data = cmdReg.cyl_high; - break; - case DRIVE_OFFSET: - *data = cmdReg.drive; - break; - case STATUS_OFFSET: - *data = status; - action = ACT_STAT_READ; - break; - default: - panic("Invalid IDE command register offset: %#x\n", offset); + if (offset == DATA_OFFSET) { + if (size == sizeof(uint16_t)) { + *(uint16_t *)data = cmdReg.data; + } else if (size == sizeof(uint32_t)) { + *(uint16_t *)data = cmdReg.data; + updateState(ACT_DATA_READ_SHORT); + *((uint16_t *)data + 1) = cmdReg.data; + } else { + panic("Data read of unsupported size %d.\n", size); } + updateState(ACT_DATA_READ_SHORT); + return; + } + assert(size == sizeof(uint8_t)); + switch (offset) { + case ERROR_OFFSET: + *data = cmdReg.error; break; - case CONTROL_BLOCK: - if (offset == ALTSTAT_OFFSET) - *data = status; - else - panic("Invalid IDE control register offset: %#x\n", offset); + case NSECTOR_OFFSET: + *data = cmdReg.sec_count; + break; + case SECTOR_OFFSET: + *data = cmdReg.sec_num; + break; + case LCYL_OFFSET: + *data = cmdReg.cyl_low; + break; + case HCYL_OFFSET: + *data = cmdReg.cyl_high; + break; + case DRIVE_OFFSET: + *data = cmdReg.drive; + break; + case STATUS_OFFSET: + *data = status; + updateState(ACT_STAT_READ); break; default: - panic("Unknown register block!\n"); + panic("Invalid IDE command register offset: %#x\n", offset); } - DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, - (uint32_t)*data); - - if (action != ACT_NONE) - updateState(action); + DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data); } void -IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data) +IdeDisk::readControl(const Addr offset, int size, uint8_t *data) { - DevAction_t action = ACT_NONE; + assert(size == sizeof(uint8_t)); + *data = status; + if (offset != ALTSTAT_OFFSET) + panic("Invalid IDE control register offset: %#x\n", offset); + DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data); +} - switch (reg_type) { - case COMMAND_BLOCK: - switch (offset) { - case DATA_OFFSET: - cmdReg.data = *(uint16_t*)data; - action = ACT_DATA_WRITE_SHORT; - break; - case FEATURES_OFFSET: - break; - case NSECTOR_OFFSET: - cmdReg.sec_count = *data; - break; - case SECTOR_OFFSET: - cmdReg.sec_num = *data; - break; - case LCYL_OFFSET: - cmdReg.cyl_low = *data; - break; - case HCYL_OFFSET: - cmdReg.cyl_high = *data; - break; - case DRIVE_OFFSET: - cmdReg.drive = *data; - action = ACT_SELECT_WRITE; - break; - case COMMAND_OFFSET: - cmdReg.command = *data; - action = ACT_CMD_WRITE; - break; - default: - panic("Invalid IDE command register offset: %#x\n", offset); +void +IdeDisk::writeCommand(const Addr offset, int size, const uint8_t *data) +{ + if (offset == DATA_OFFSET) { + if (size == sizeof(uint16_t)) { + cmdReg.data = *(const uint16_t *)data; + } else if (size == sizeof(uint32_t)) { + cmdReg.data = *(const uint16_t *)data; + updateState(ACT_DATA_WRITE_SHORT); + cmdReg.data = *((const uint16_t *)data + 1); + } else { + panic("Data write of unsupported size %d.\n", size); } + updateState(ACT_DATA_WRITE_SHORT); + return; + } + + assert(size == sizeof(uint8_t)); + switch (offset) { + case FEATURES_OFFSET: break; - case CONTROL_BLOCK: - if (offset == CONTROL_OFFSET) { - if (*data & CONTROL_RST_BIT) { - // force the device into the reset state - devState = Device_Srst; - action = ACT_SRST_SET; - } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) - action = ACT_SRST_CLEAR; - - nIENBit = (*data & CONTROL_IEN_BIT) ? true : false; - } - else - panic("Invalid IDE control register offset: %#x\n", offset); + case NSECTOR_OFFSET: + cmdReg.sec_count = *data; + break; + case SECTOR_OFFSET: + cmdReg.sec_num = *data; + break; + case LCYL_OFFSET: + cmdReg.cyl_low = *data; + break; + case HCYL_OFFSET: + cmdReg.cyl_high = *data; + break; + case DRIVE_OFFSET: + cmdReg.drive = *data; + updateState(ACT_SELECT_WRITE); + break; + case COMMAND_OFFSET: + cmdReg.command = *data; + updateState(ACT_CMD_WRITE); break; default: - panic("Unknown register block!\n"); + panic("Invalid IDE command register offset: %#x\n", offset); + } + DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset, + (uint32_t)*data); +} + +void +IdeDisk::writeControl(const Addr offset, int size, const uint8_t *data) +{ + if (offset != CONTROL_OFFSET) + panic("Invalid IDE control register offset: %#x\n", offset); + + if (*data & CONTROL_RST_BIT) { + // force the device into the reset state + devState = Device_Srst; + updateState(ACT_SRST_SET); + } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) { + updateState(ACT_SRST_CLEAR); } + nIENBit = *data & CONTROL_IEN_BIT; + DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset, (uint32_t)*data); - if (action != ACT_NONE) - updateState(action); } //// @@ -319,7 +322,7 @@ IdeDisk::doDmaTransfer() dmaState, devState); if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { - dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + schedule(dmaTransferEvent, curTick + DMA_BACKOFF_PERIOD); return; } else ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent, @@ -353,7 +356,7 @@ IdeDisk::doDmaDataRead() DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n", diskDelay, totalDiskDelay); - dmaReadWaitEvent.schedule(curTick + totalDiskDelay); + schedule(dmaReadWaitEvent, curTick + totalDiskDelay); } void @@ -399,7 +402,7 @@ IdeDisk::doDmaRead() } if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { - dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + schedule(dmaReadWaitEvent, curTick + DMA_BACKOFF_PERIOD); return; } else if (!dmaReadCG->done()) { assert(dmaReadCG->complete() < MAX_DMA_SIZE); @@ -461,7 +464,7 @@ IdeDisk::doDmaDataWrite() cmdBytesLeft -= SectorSize; } - dmaWriteWaitEvent.schedule(curTick + totalDiskDelay); + schedule(dmaWriteWaitEvent, curTick + totalDiskDelay); } void @@ -474,7 +477,7 @@ IdeDisk::doDmaWrite() curPrd.getByteCount(), TheISA::PageBytes); } if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { - dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + schedule(dmaWriteWaitEvent, curTick + DMA_BACKOFF_PERIOD); return; } else if (!dmaWriteCG->done()) { assert(dmaWriteCG->complete() < MAX_DMA_SIZE); @@ -549,7 +552,7 @@ IdeDisk::startDma(const uint32_t &prdTableBase) dmaState = Dma_Transfer; // schedule dma transfer (doDmaTransfer) - dmaTransferEvent.schedule(curTick + 1); + schedule(dmaTransferEvent, curTick + 1); } void @@ -687,7 +690,6 @@ IdeDisk::intrPost() // talk to controller to set interrupt if (ctrl) { - ctrl->bmi_regs.bmis0 |= IDEINTS; ctrl->intrPost(); } } @@ -1077,12 +1079,12 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion) switch (event) { case None : break; - case Transfer : dmaTransferEvent.schedule(reschedule); break; - case ReadWait : dmaReadWaitEvent.schedule(reschedule); break; - case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break; - case PrdRead : dmaPrdReadEvent.schedule(reschedule); break; - case DmaRead : dmaReadEvent.schedule(reschedule); break; - case DmaWrite : dmaWriteEvent.schedule(reschedule); break; + case Transfer : schedule(dmaTransferEvent, reschedule); break; + case ReadWait : schedule(dmaReadWaitEvent, reschedule); break; + case WriteWait : schedule(dmaWriteWaitEvent, reschedule); break; + case PrdRead : schedule(dmaPrdReadEvent, reschedule); break; + case DmaRead : schedule(dmaReadEvent, reschedule); break; + case DmaWrite : schedule(dmaWriteEvent, reschedule); break; } // Unserialize device registers @@ -1116,32 +1118,8 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE); } -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -enum DriveID { master, slave }; -static const char *DriveID_strings[] = { "master", "slave" }; -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) - - SimObjectParam image; - SimpleEnumParam driveID; - Param delay; - -END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk) - - INIT_PARAM(image, "Disk image"), - INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings), - INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1) - -END_INIT_SIM_OBJECT_PARAMS(IdeDisk) - - -CREATE_SIM_OBJECT(IdeDisk) +IdeDisk * +IdeDiskParams::create() { - return new IdeDisk(getInstanceName(), image, driveID, delay); + return new IdeDisk(this); } - -REGISTER_SIM_OBJECT("IdeDisk", IdeDisk) - -#endif //DOXYGEN_SHOULD_SKIP_THIS