#include <deque>
#include <string>
-#include "arch/alpha/pmap.h"
#include "base/cprintf.hh" // csprintf
#include "base/trace.hh"
#include "dev/disk_image.hh"
#include "mem/bus/pio_interface_impl.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
-#include "sim/universe.hh"
+#include "sim/root.hh"
+#include "targetarch/isa_traits.hh"
using namespace std;
IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
- int id, int delay)
- : SimObject(name), ctrl(NULL), image(img), physmem(phys),
+ int id, Tick delay)
+ : SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay),
dmaTransferEvent(this), dmaReadWaitEvent(this),
dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this)
// Reset the device state
reset(id);
- // calculate disk delay in microseconds
- diskDelay = (delay * ticksPerSecond / 100000);
-
// fill out the drive ID structure
- memset(&driveID, 0, sizeof(struct hd_driveid));
+ memset(&driveID, 0, sizeof(struct ataparams));
// Calculate LBA and C/H/S values
uint16_t cylinders;
}
// Setup the model name
- sprintf((char *)driveID.model, "5MI EDD si k");
+ sprintf((char *)driveID.atap_model, "5MI EDD si k");
// Set the maximum multisector transfer size
- driveID.max_multsect = MAX_MULTSECT;
+ driveID.atap_multi = MAX_MULTSECT;
// IORDY supported, IORDY disabled, LBA enabled, DMA enabled
- driveID.capability = 0x7;
+ driveID.atap_capabilities1 = 0x7;
// UDMA support, EIDE support
- driveID.field_valid = 0x6;
+ driveID.atap_extensions = 0x6;
// Setup default C/H/S settings
- driveID.cyls = cylinders;
- driveID.sectors = sectors;
- driveID.heads = heads;
+ driveID.atap_cylinders = cylinders;
+ driveID.atap_sectors = sectors;
+ driveID.atap_heads = heads;
// Setup the current multisector transfer size
- driveID.multsect = MAX_MULTSECT;
- driveID.multsect_valid = 0x1;
+ driveID.atap_curmulti = MAX_MULTSECT;
+ driveID.atap_curmulti_valid = 0x1;
// Number of sectors on disk
- driveID.lba_capacity = lba_size;
+ driveID.atap_capacity = lba_size;
// Multiword DMA mode 2 and below supported
- driveID.dma_mword = 0x400;
+ driveID.atap_dmamode_supp = 0x400;
// Set PIO mode 4 and 3 supported
- driveID.eide_pio_modes = 0x3;
+ driveID.atap_piomode_supp = 0x3;
// Set DMA mode 4 and below supported
- driveID.dma_ultra = 0x10;
+ driveID.atap_udmamode_supp = 0x10;
// Statically set hardware config word
- driveID.hw_config = 0x4001;
+ driveID.atap_hwreset_res = 0x4001;
}
IdeDisk::~IdeDisk()
IdeDisk::pciToDma(Addr pciAddr)
{
if (ctrl)
- return ctrl->tsunami->pchip->translatePciToDma(pciAddr);
+ return ctrl->plat->pciToDma(pciAddr);
else
panic("Access to unset controller!\n");
}
uint32_t bytesInPage = 0;
// First calculate how many bytes could be in the page
- if (bytesLeft > ALPHA_PGBYTES)
- bytesInPage = ALPHA_PGBYTES;
+ if (bytesLeft > TheISA::PageBytes)
+ bytesInPage = TheISA::PageBytes;
else
bytesInPage = bytesLeft;
// Next, see if we have crossed a page boundary, and adjust
Addr upperBound = curAddr + bytesInPage;
- Addr pageBound = alpha_trunc_page(curAddr) + ALPHA_PGBYTES;
+ Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes;
assert(upperBound >= curAddr && "DMA read wraps around address space!\n");
physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)),
sizeof(PrdEntry_t));
- DPRINTF(IdeDisk, "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
+ DPRINTF(IdeDisk,
+ "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
curPrd.getEOT(), curSector);
- // make sure the new curPrdAddr is properly translated from PCI to system
- curPrdAddr = pciToDma(curPrdAddr + sizeof(PrdEntry_t));
+ // the prd pointer has already been translated, so just do an increment
+ curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
if (dmaRead)
doDmaRead();
void
IdeDisk::doDmaRead()
{
+ /** @TODO we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
+ DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
+ diskDelay, totalDiskDelay);
if (dmaInterface) {
if (dmaInterface->busy()) {
// reschedule after waiting period
void
IdeDisk::doDmaWrite()
{
+ /** @TODO we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
+ DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
+ diskDelay, totalDiskDelay);
+
if (dmaInterface) {
if (dmaInterface->busy()) {
// reschedule after waiting period
// setup the initial page and DMA address
curAddr = curPrd.getBaseAddr();
- pageAddr = alpha_trunc_page(curAddr);
+ pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
// clear out the data buffer
while (bytesRead < curPrd.getByteCount()) {
// see if we have crossed into a new page
- if (pageAddr != alpha_trunc_page(curAddr)) {
+ if (pageAddr != TheISA::TruncPage(curAddr)) {
// write the data to memory
memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)),
bytesInPage);
// update the DMA address and page address
- pageAddr = alpha_trunc_page(curAddr);
+ pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
bytesInPage = 0;
IdeDisk::abortDma()
{
if (dmaState == Dma_Idle)
- panic("Inconsistent DMA state, should be in Dma_Start or Dma_Transfer!\n");
+ panic("Inconsistent DMA state, should be Start or Transfer!");
if (devState != Transfer_Data_Dma && devState != Prepare_Data_Dma)
- panic("Inconsistent device state, should be in Transfer or Prepare!\n");
+ panic("Inconsistent device state, should be Transfer or Prepare!\n");
updateState(ACT_CMD_ERROR);
}
// Decode commands
switch (cmdReg.command) {
// Supported non-data commands
- case WIN_READ_NATIVE_MAX:
+ case WDSF_READ_NATIVE_MAX:
size = image->size() - 1;
cmdReg.sec_num = (size & 0xff);
cmdReg.cyl_low = ((size & 0xff00) >> 8);
action = ACT_CMD_COMPLETE;
break;
- case WIN_RECAL:
- case WIN_SPECIFY:
- case WIN_STANDBYNOW1:
- case WIN_FLUSH_CACHE:
- case WIN_VERIFY:
- case WIN_SEEK:
- case WIN_SETFEATURES:
- case WIN_SETMULT:
+ case WDCC_RECAL:
+ case WDCC_IDP:
+ case WDCC_STANDBY_IMMED:
+ case WDCC_FLUSHCACHE:
+ case WDSF_VERIFY:
+ case WDSF_SEEK:
+ case SET_FEATURES:
+ case WDCC_SETMULTI:
devState = Command_Execution;
action = ACT_CMD_COMPLETE;
break;
// Supported PIO data-in commands
- case WIN_IDENTIFY:
- cmdBytes = cmdBytesLeft = sizeof(struct hd_driveid);
+ case WDCC_IDENTIFY:
+ cmdBytes = cmdBytesLeft = sizeof(struct ataparams);
devState = Prepare_Data_In;
action = ACT_DATA_READY;
break;
- case WIN_MULTREAD:
- case WIN_READ:
+ case WDCC_READMULTI:
+ case WDCC_READ:
if (!(cmdReg.drive & DRIVE_LBA_BIT))
panic("Attempt to perform CHS access, only supports LBA\n");
break;
// Supported PIO data-out commands
- case WIN_MULTWRITE:
- case WIN_WRITE:
+ case WDCC_WRITEMULTI:
+ case WDCC_WRITE:
if (!(cmdReg.drive & DRIVE_LBA_BIT))
panic("Attempt to perform CHS access, only supports LBA\n");
break;
// Supported DMA commands
- case WIN_WRITEDMA:
+ case WDCC_WRITEDMA:
dmaRead = true; // a write to the disk is a DMA read from memory
- case WIN_READDMA:
+ case WDCC_READDMA:
if (!(cmdReg.drive & DRIVE_LBA_BIT))
panic("Attempt to perform CHS access, only supports LBA\n");
void
IdeDisk::intrPost()
{
+ DPRINTF(IdeDisk, "Posting Interrupt\n");
if (intrPending)
panic("Attempt to post an interrupt with one pending\n");
void
IdeDisk::intrClear()
{
+ DPRINTF(IdeDisk, "Clearing Interrupt\n");
if (!intrPending)
panic("Attempt to clear a non-pending interrupt\n");
status |= STATUS_DRQ_BIT;
// copy the data into the data buffer
- if (cmdReg.command == WIN_IDENTIFY) {
+ if (cmdReg.command == WDCC_IDENTIFY) {
// Reset the drqBytes for this block
- drqBytesLeft = sizeof(struct hd_driveid);
+ drqBytesLeft = sizeof(struct ataparams);
memcpy((void *)dataBuffer, (void *)&driveID,
- sizeof(struct hd_driveid));
+ sizeof(struct ataparams));
} else {
// Reset the drqBytes for this block
drqBytesLeft = SectorSize;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
+enum DriveID { master, slave };
+static const char *DriveID_strings[] = { "master", "slave" };
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
SimObjectParam<DiskImage *> image;
SimObjectParam<PhysicalMemory *> physmem;
- Param<int> driveID;
- Param<int> disk_delay;
+ SimpleEnumParam<DriveID> driveID;
+ Param<int> delay;
END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"),
INIT_PARAM(physmem, "Physical memory"),
- INIT_PARAM(driveID, "Drive ID (0=master 1=slave)"),
- INIT_PARAM_DFLT(disk_delay, "Fixed disk delay in microseconds", 1)
+ 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)
{
- return new IdeDisk(getInstanceName(), image, physmem, driveID,
- disk_delay);
+ return new IdeDisk(getInstanceName(), image, physmem, driveID, delay);
}
REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)