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 §ion){ // 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 + -
显示快捷键?