X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=dev%2Fide_disk.cc;h=dbb2792e135dabb57a779cac799281b9aff8fa6f;hb=8bbaaa7478bdddcd098c4da97f4ac1ba5a97ee67;hp=dcaaf64c84b45f7a78162f4aa74d1502b3a15bf4;hpb=0408051f201cb5b19c4f8d5ec1d6e96de4a9aa3f;p=gem5.git diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index dcaaf64c8..dbb2792e1 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,7 +35,6 @@ #include #include -#include "arch/alpha/pmap.h" #include "base/cprintf.hh" // csprintf #include "base/trace.hh" #include "dev/disk_image.hh" @@ -50,13 +49,14 @@ #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) @@ -64,11 +64,8 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, // 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; @@ -95,30 +92,30 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, } // 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() @@ -167,11 +164,17 @@ IdeDisk::reset(int id) // Utility functions //// +bool +IdeDisk::isDEVSelect() +{ + return ctrl->isDiskSelected(this); +} + Addr IdeDisk::pciToDma(Addr pciAddr) { if (ctrl) - return ctrl->tsunami->pchip->translatePciToDma(pciAddr); + return ctrl->plat->pciToDma(pciAddr); else panic("Access to unset controller!\n"); } @@ -182,14 +185,14 @@ IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft) 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"); @@ -330,13 +333,14 @@ IdeDisk::dmaPrdReadDone() 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(); @@ -347,8 +351,11 @@ IdeDisk::dmaPrdReadDone() 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 @@ -435,29 +442,8 @@ IdeDisk::dmaReadDone() writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); } -#if 0 - // actually copy the data from memory to data buffer - Addr dmaAddr = - ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr()); - memcpy((void *)dataBuffer, - physmem->dma_addr(dmaAddr, curPrd.getByteCount()), - curPrd.getByteCount()); - - uint32_t bytesWritten = 0; - - while (bytesWritten < curPrd.getByteCount()) { - if (cmdBytesLeft <= 0) - panic("DMA data is larger than # sectors specified\n"); - - writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); - - bytesWritten += SectorSize; - cmdBytesLeft -= SectorSize; - } -#endif - // check for the EOT - if (curPrd.getEOT()){ + if (curPrd.getEOT()) { assert(cmdBytesLeft == 0); dmaState = Dma_Idle; updateState(ACT_DMA_DONE); @@ -469,8 +455,12 @@ IdeDisk::dmaReadDone() 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 @@ -525,7 +515,7 @@ IdeDisk::dmaWriteDone() // 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 @@ -533,14 +523,14 @@ IdeDisk::dmaWriteDone() 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; @@ -564,14 +554,6 @@ IdeDisk::dmaWriteDone() bytesInPage); } -#if 0 - Addr dmaAddr = ctrl->tsunami->pchip-> - translatePciToDma(curPrd.getBaseAddr()); - - memcpy(physmem->dma_addr(dmaAddr, curPrd.getByteCount()), - (void *)dataBuffer, curPrd.getByteCount()); -#endif - // check for the EOT if (curPrd.getEOT()) { assert(cmdBytesLeft == 0); @@ -632,10 +614,10 @@ void 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); } @@ -650,7 +632,7 @@ IdeDisk::startCommand() // 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); @@ -661,27 +643,27 @@ IdeDisk::startCommand() 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"); @@ -698,8 +680,8 @@ IdeDisk::startCommand() 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"); @@ -715,9 +697,9 @@ IdeDisk::startCommand() 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"); @@ -755,6 +737,7 @@ IdeDisk::startCommand() void IdeDisk::intrPost() { + DPRINTF(IdeDisk, "Posting Interrupt\n"); if (intrPending) panic("Attempt to post an interrupt with one pending\n"); @@ -768,6 +751,7 @@ IdeDisk::intrPost() void IdeDisk::intrClear() { + DPRINTF(IdeDisk, "Clearing Interrupt\n"); if (!intrPending) panic("Attempt to clear a non-pending interrupt\n"); @@ -866,12 +850,12 @@ IdeDisk::updateState(DevAction_t action) 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; @@ -1067,26 +1051,41 @@ IdeDisk::serialize(ostream &os) Tick reschedule = 0; Events_t event = None; + int eventCount = 0; + if (dmaTransferEvent.scheduled()) { reschedule = dmaTransferEvent.when(); event = Transfer; - } else if (dmaReadWaitEvent.scheduled()) { + eventCount++; + } + if (dmaReadWaitEvent.scheduled()) { reschedule = dmaReadWaitEvent.when(); event = ReadWait; - } else if (dmaWriteWaitEvent.scheduled()) { + eventCount++; + } + if (dmaWriteWaitEvent.scheduled()) { reschedule = dmaWriteWaitEvent.when(); event = WriteWait; - } else if (dmaPrdReadEvent.scheduled()) { + eventCount++; + } + if (dmaPrdReadEvent.scheduled()) { reschedule = dmaPrdReadEvent.when(); event = PrdRead; - } else if (dmaReadEvent.scheduled()) { + eventCount++; + } + if (dmaReadEvent.scheduled()) { reschedule = dmaReadEvent.when(); event = DmaRead; - } else if (dmaWriteEvent.scheduled()) { + eventCount++; + } + if (dmaWriteEvent.scheduled()) { reschedule = dmaWriteEvent.when(); event = DmaWrite; + eventCount++; } + assert(eventCount <= 1); + SERIALIZE_SCALAR(reschedule); SERIALIZE_ENUM(event); @@ -1098,6 +1097,7 @@ IdeDisk::serialize(ostream &os) SERIALIZE_SCALAR(cmdReg.cyl_low); SERIALIZE_SCALAR(cmdReg.cyl_high); SERIALIZE_SCALAR(cmdReg.drive); + SERIALIZE_SCALAR(cmdReg.command); SERIALIZE_SCALAR(status); SERIALIZE_SCALAR(nIENBit); SERIALIZE_SCALAR(devID); @@ -1150,6 +1150,7 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(cmdReg.cyl_low); UNSERIALIZE_SCALAR(cmdReg.cyl_high); UNSERIALIZE_SCALAR(cmdReg.drive); + UNSERIALIZE_SCALAR(cmdReg.command); UNSERIALIZE_SCALAR(status); UNSERIALIZE_SCALAR(nIENBit); UNSERIALIZE_SCALAR(devID); @@ -1175,12 +1176,14 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion) #ifndef DOXYGEN_SHOULD_SKIP_THIS +enum DriveID { master, slave }; +static const char *DriveID_strings[] = { "master", "slave" }; BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) SimObjectParam image; SimObjectParam physmem; - Param driveID; - Param disk_delay; + SimpleEnumParam driveID; + Param delay; END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) @@ -1188,16 +1191,15 @@ BEGIN_INIT_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)