ide_disk.cc

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 1,120 行 · 第 1/3 页

CC
1,120
字号
      case Device_Idle_NS:        if (action == ACT_SELECT_WRITE && isDEVSelect()) {            if (!isIENSet() && intrPending) {                devState = Device_Idle_SI;                intrPost();            }            if (isIENSet() || !intrPending) {                devState = Device_Idle_S;            }        }        break;      case Command_Execution:        if (action == ACT_CMD_COMPLETE) {            // clear the BSY bit            setComplete();            if (!isIENSet()) {                devState = Device_Idle_SI;                intrPost();            } else {                devState = Device_Idle_S;            }        }        break;      case Prepare_Data_In:        if (action == ACT_CMD_ERROR) {            // clear the BSY bit            setComplete();            if (!isIENSet()) {                devState = Device_Idle_SI;                intrPost();            } else {                devState = Device_Idle_S;            }        } else if (action == ACT_DATA_READY) {            // clear the BSY bit            status &= ~STATUS_BSY_BIT;            // set the DRQ bit            status |= STATUS_DRQ_BIT;            // copy the data into the data buffer            if (cmdReg.command == WDCC_IDENTIFY) {                // Reset the drqBytes for this block                drqBytesLeft = sizeof(struct ataparams);                memcpy((void *)dataBuffer, (void *)&driveID,                       sizeof(struct ataparams));            } else {                // Reset the drqBytes for this block                drqBytesLeft = SectorSize;                readDisk(curSector++, dataBuffer);            }            // put the first two bytes into the data register            memcpy((void *)&cmdReg.data, (void *)dataBuffer,                   sizeof(uint16_t));            if (!isIENSet()) {                devState = Data_Ready_INTRQ_In;                intrPost();            } else {                devState = Transfer_Data_In;            }        }        break;      case Data_Ready_INTRQ_In:        if (action == ACT_STAT_READ) {            devState = Transfer_Data_In;            intrClear();        }        break;      case Transfer_Data_In:        if (action == ACT_DATA_READ_BYTE || action == ACT_DATA_READ_SHORT) {            if (action == ACT_DATA_READ_BYTE) {                panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n");            } else {                drqBytesLeft -= 2;                cmdBytesLeft -= 2;                // copy next short into data registers                if (drqBytesLeft)                    memcpy((void *)&cmdReg.data,                           (void *)&dataBuffer[SectorSize - drqBytesLeft],                           sizeof(uint16_t));            }            if (drqBytesLeft == 0) {                if (cmdBytesLeft == 0) {                    // Clear the BSY bit                    setComplete();                    devState = Device_Idle_S;                } else {                    devState = Prepare_Data_In;                    // set the BSY_BIT                    status |= STATUS_BSY_BIT;                    // clear the DRQ_BIT                    status &= ~STATUS_DRQ_BIT;                    /** @todo change this to a scheduled event to simulate                        disk delay */                    updateState(ACT_DATA_READY);                }            }        }        break;      case Prepare_Data_Out:        if (action == ACT_CMD_ERROR || cmdBytesLeft == 0) {            // clear the BSY bit            setComplete();            if (!isIENSet()) {                devState = Device_Idle_SI;                intrPost();            } else {                devState = Device_Idle_S;            }        } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {            // clear the BSY bit            status &= ~STATUS_BSY_BIT;            // set the DRQ bit            status |= STATUS_DRQ_BIT;            // clear the data buffer to get it ready for writes            memset(dataBuffer, 0, MAX_DMA_SIZE);            // reset the drqBytes for this block            drqBytesLeft = SectorSize;            if (cmdBytesLeft == cmdBytes || isIENSet()) {                devState = Transfer_Data_Out;            } else {                devState = Data_Ready_INTRQ_Out;                intrPost();            }        }        break;      case Data_Ready_INTRQ_Out:        if (action == ACT_STAT_READ) {            devState = Transfer_Data_Out;            intrClear();        }        break;      case Transfer_Data_Out:        if (action == ACT_DATA_WRITE_BYTE ||            action == ACT_DATA_WRITE_SHORT) {            if (action == ACT_DATA_READ_BYTE) {                panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");            } else {                // copy the latest short into the data buffer                memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],                       (void *)&cmdReg.data,                       sizeof(uint16_t));                drqBytesLeft -= 2;                cmdBytesLeft -= 2;            }            if (drqBytesLeft == 0) {                // copy the block to the disk                writeDisk(curSector++, dataBuffer);                // set the BSY bit                status |= STATUS_BSY_BIT;                // set the seek bit                status |= STATUS_SEEK_BIT;                // clear the DRQ bit                status &= ~STATUS_DRQ_BIT;                devState = Prepare_Data_Out;                /** @todo change this to a scheduled event to simulate                    disk delay */                updateState(ACT_DATA_READY);            }        }        break;      case Prepare_Data_Dma:        if (action == ACT_CMD_ERROR) {            // clear the BSY bit            setComplete();            if (!isIENSet()) {                devState = Device_Idle_SI;                intrPost();            } else {                devState = Device_Idle_S;            }        } else if (action == ACT_DMA_READY) {            // clear the BSY bit            status &= ~STATUS_BSY_BIT;            // set the DRQ bit            status |= STATUS_DRQ_BIT;            devState = Transfer_Data_Dma;            if (dmaState != Dma_Idle)                panic("Inconsistent DMA state, should be Dma_Idle\n");            dmaState = Dma_Start;            // wait for the write to the DMA start bit        }        break;      case Transfer_Data_Dma:        if (action == ACT_CMD_ERROR || action == ACT_DMA_DONE) {            // clear the BSY bit            setComplete();            // set the seek bit            status |= STATUS_SEEK_BIT;            // clear the controller state for DMA transfer            ctrl->setDmaComplete(this);            if (!isIENSet()) {                devState = Device_Idle_SI;                intrPost();            } else {                devState = Device_Idle_S;            }        }        break;      default:        panic("Unknown IDE device state: %#x\n", devState);    }}voidIdeDisk::serialize(ostream &os){    // Check all outstanding events to see if they are scheduled    // these are all mutually exclusive    Tick reschedule = 0;    Events_t event = None;    int eventCount = 0;    if (dmaTransferEvent.scheduled()) {        reschedule = dmaTransferEvent.when();        event = Transfer;        eventCount++;    }    if (dmaReadWaitEvent.scheduled()) {        reschedule = dmaReadWaitEvent.when();        event = ReadWait;        eventCount++;    }    if (dmaWriteWaitEvent.scheduled()) {        reschedule = dmaWriteWaitEvent.when();        event = WriteWait;        eventCount++;    }    if (dmaPrdReadEvent.scheduled()) {        reschedule = dmaPrdReadEvent.when();        event = PrdRead;        eventCount++;    }    if (dmaReadEvent.scheduled()) {        reschedule = dmaReadEvent.when();        event = DmaRead;        eventCount++;    }    if (dmaWriteEvent.scheduled()) {        reschedule = dmaWriteEvent.when();        event = DmaWrite;        eventCount++;    }    assert(eventCount <= 1);    SERIALIZE_SCALAR(reschedule);    SERIALIZE_ENUM(event);    // Serialize device registers    SERIALIZE_SCALAR(cmdReg.data);    SERIALIZE_SCALAR(cmdReg.sec_count);    SERIALIZE_SCALAR(cmdReg.sec_num);    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);    // Serialize the PRD related information    SERIALIZE_SCALAR(curPrd.entry.baseAddr);    SERIALIZE_SCALAR(curPrd.entry.byteCount);    SERIALIZE_SCALAR(curPrd.entry.endOfTable);    SERIALIZE_SCALAR(curPrdAddr);    /** @todo need to serialized chunk generator stuff!! */    // Serialize current transfer related information    SERIALIZE_SCALAR(cmdBytesLeft);    SERIALIZE_SCALAR(cmdBytes);    SERIALIZE_SCALAR(drqBytesLeft);    SERIALIZE_SCALAR(curSector);    SERIALIZE_SCALAR(dmaRead);    SERIALIZE_SCALAR(intrPending);    SERIALIZE_ENUM(devState);    SERIALIZE_ENUM(dmaState);    SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);}voidIdeDisk::unserialize(Checkpoint *cp, const string &section){    // Reschedule events that were outstanding    // these are all mutually exclusive    Tick reschedule = 0;    Events_t event = None;    UNSERIALIZE_SCALAR(reschedule);    UNSERIALIZE_ENUM(event);    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;    }    // Unserialize device registers    UNSERIALIZE_SCALAR(cmdReg.data);    UNSERIALIZE_SCALAR(cmdReg.sec_count);    UNSERIALIZE_SCALAR(cmdReg.sec_num);    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);    // Unserialize the PRD related information    UNSERIALIZE_SCALAR(curPrd.entry.baseAddr);    UNSERIALIZE_SCALAR(curPrd.entry.byteCount);    UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);    UNSERIALIZE_SCALAR(curPrdAddr);    /** @todo need to serialized chunk generator stuff!! */    // Unserialize current transfer related information    UNSERIALIZE_SCALAR(cmdBytes);    UNSERIALIZE_SCALAR(cmdBytesLeft);    UNSERIALIZE_SCALAR(drqBytesLeft);    UNSERIALIZE_SCALAR(curSector);    UNSERIALIZE_SCALAR(dmaRead);    UNSERIALIZE_SCALAR(intrPending);    UNSERIALIZE_ENUM(devState);    UNSERIALIZE_ENUM(dmaState);    UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);}IdeDisk *IdeDiskParams::create(){    return new IdeDisk(this);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?