gem5/src/dev/ide_disk.hh
Kevin Lim 4ed184eade Merge ktlim@zamp:./local/clean/o3-merge/m5
into  zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem

configs/boot/micro_memlat.rcS:
configs/boot/micro_tlblat.rcS:
src/arch/alpha/ev5.cc:
src/arch/alpha/isa/decoder.isa:
src/arch/alpha/isa_traits.hh:
src/cpu/base.cc:
src/cpu/base.hh:
src/cpu/base_dyn_inst.hh:
src/cpu/checker/cpu.hh:
src/cpu/checker/cpu_impl.hh:
src/cpu/o3/alpha/cpu_impl.hh:
src/cpu/o3/alpha/params.hh:
src/cpu/o3/checker_builder.cc:
src/cpu/o3/commit_impl.hh:
src/cpu/o3/cpu.cc:
src/cpu/o3/decode_impl.hh:
src/cpu/o3/fetch_impl.hh:
src/cpu/o3/iew.hh:
src/cpu/o3/iew_impl.hh:
src/cpu/o3/inst_queue.hh:
src/cpu/o3/lsq.hh:
src/cpu/o3/lsq_impl.hh:
src/cpu/o3/lsq_unit.hh:
src/cpu/o3/lsq_unit_impl.hh:
src/cpu/o3/regfile.hh:
src/cpu/o3/rename_impl.hh:
src/cpu/o3/thread_state.hh:
src/cpu/ozone/checker_builder.cc:
src/cpu/ozone/cpu.hh:
src/cpu/ozone/cpu_impl.hh:
src/cpu/ozone/front_end.hh:
src/cpu/ozone/front_end_impl.hh:
src/cpu/ozone/lw_back_end.hh:
src/cpu/ozone/lw_back_end_impl.hh:
src/cpu/ozone/lw_lsq.hh:
src/cpu/ozone/lw_lsq_impl.hh:
src/cpu/ozone/thread_state.hh:
src/cpu/simple/base.cc:
src/cpu/simple_thread.cc:
src/cpu/simple_thread.hh:
src/cpu/thread_state.hh:
src/dev/ide_disk.cc:
src/python/m5/objects/O3CPU.py:
src/python/m5/objects/Root.py:
src/python/m5/objects/System.py:
src/sim/pseudo_inst.cc:
src/sim/pseudo_inst.hh:
src/sim/system.hh:
util/m5/m5.c:
    Hand merge.

--HG--
rename : arch/alpha/ev5.cc => src/arch/alpha/ev5.cc
rename : arch/alpha/freebsd/system.cc => src/arch/alpha/freebsd/system.cc
rename : arch/alpha/isa/decoder.isa => src/arch/alpha/isa/decoder.isa
rename : arch/alpha/isa/mem.isa => src/arch/alpha/isa/mem.isa
rename : arch/alpha/isa_traits.hh => src/arch/alpha/isa_traits.hh
rename : arch/alpha/linux/system.cc => src/arch/alpha/linux/system.cc
rename : arch/alpha/system.cc => src/arch/alpha/system.cc
rename : arch/alpha/tru64/system.cc => src/arch/alpha/tru64/system.cc
rename : cpu/base.cc => src/cpu/base.cc
rename : cpu/base.hh => src/cpu/base.hh
rename : cpu/base_dyn_inst.hh => src/cpu/base_dyn_inst.hh
rename : cpu/checker/cpu.hh => src/cpu/checker/cpu.hh
rename : cpu/checker/cpu.cc => src/cpu/checker/cpu_impl.hh
rename : cpu/o3/alpha_cpu_builder.cc => src/cpu/o3/alpha/cpu_builder.cc
rename : cpu/checker/o3_cpu_builder.cc => src/cpu/o3/checker_builder.cc
rename : cpu/o3/commit_impl.hh => src/cpu/o3/commit_impl.hh
rename : cpu/o3/cpu.cc => src/cpu/o3/cpu.cc
rename : cpu/o3/fetch_impl.hh => src/cpu/o3/fetch_impl.hh
rename : cpu/o3/iew.hh => src/cpu/o3/iew.hh
rename : cpu/o3/iew_impl.hh => src/cpu/o3/iew_impl.hh
rename : cpu/o3/inst_queue.hh => src/cpu/o3/inst_queue.hh
rename : cpu/o3/inst_queue_impl.hh => src/cpu/o3/inst_queue_impl.hh
rename : cpu/o3/lsq_impl.hh => src/cpu/o3/lsq_impl.hh
rename : cpu/o3/lsq_unit.hh => src/cpu/o3/lsq_unit.hh
rename : cpu/o3/lsq_unit_impl.hh => src/cpu/o3/lsq_unit_impl.hh
rename : cpu/o3/mem_dep_unit_impl.hh => src/cpu/o3/mem_dep_unit_impl.hh
rename : cpu/o3/rename.hh => src/cpu/o3/rename.hh
rename : cpu/o3/rename_impl.hh => src/cpu/o3/rename_impl.hh
rename : cpu/o3/thread_state.hh => src/cpu/o3/thread_state.hh
rename : cpu/o3/tournament_pred.cc => src/cpu/o3/tournament_pred.cc
rename : cpu/o3/tournament_pred.hh => src/cpu/o3/tournament_pred.hh
rename : cpu/checker/cpu_builder.cc => src/cpu/ozone/checker_builder.cc
rename : cpu/ozone/cpu.hh => src/cpu/ozone/cpu.hh
rename : cpu/ozone/cpu_builder.cc => src/cpu/ozone/cpu_builder.cc
rename : cpu/ozone/cpu_impl.hh => src/cpu/ozone/cpu_impl.hh
rename : cpu/ozone/front_end.hh => src/cpu/ozone/front_end.hh
rename : cpu/ozone/front_end_impl.hh => src/cpu/ozone/front_end_impl.hh
rename : cpu/ozone/inorder_back_end_impl.hh => src/cpu/ozone/inorder_back_end_impl.hh
rename : cpu/ozone/inst_queue_impl.hh => src/cpu/ozone/inst_queue_impl.hh
rename : cpu/ozone/lw_back_end.hh => src/cpu/ozone/lw_back_end.hh
rename : cpu/ozone/lw_back_end_impl.hh => src/cpu/ozone/lw_back_end_impl.hh
rename : cpu/ozone/lw_lsq.hh => src/cpu/ozone/lw_lsq.hh
rename : cpu/ozone/lw_lsq_impl.hh => src/cpu/ozone/lw_lsq_impl.hh
rename : cpu/ozone/simple_params.hh => src/cpu/ozone/simple_params.hh
rename : cpu/ozone/thread_state.hh => src/cpu/ozone/thread_state.hh
rename : cpu/simple/cpu.cc => src/cpu/simple/base.cc
rename : cpu/cpu_exec_context.cc => src/cpu/simple_thread.cc
rename : cpu/thread_state.hh => src/cpu/thread_state.hh
rename : dev/ide_disk.hh => src/dev/ide_disk.hh
rename : python/m5/objects/BaseCPU.py => src/python/m5/objects/BaseCPU.py
rename : python/m5/objects/AlphaFullCPU.py => src/python/m5/objects/O3CPU.py
rename : python/m5/objects/OzoneCPU.py => src/python/m5/objects/OzoneCPU.py
rename : python/m5/objects/Root.py => src/python/m5/objects/Root.py
rename : python/m5/objects/System.py => src/python/m5/objects/System.py
rename : sim/eventq.hh => src/sim/eventq.hh
rename : sim/pseudo_inst.cc => src/sim/pseudo_inst.cc
rename : sim/pseudo_inst.hh => src/sim/pseudo_inst.hh
rename : sim/serialize.cc => src/sim/serialize.cc
rename : sim/stat_control.cc => src/sim/stat_control.cc
rename : sim/stat_control.hh => src/sim/stat_control.hh
rename : sim/system.hh => src/sim/system.hh
extra : convert_revision : 135d90e43f6cea89f9460ba4e23f4b0b85886e7d
2006-09-30 23:43:23 -04:00

376 lines
9.5 KiB
C++

/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andrew Schultz
*/
/** @file
* Device model for an IDE disk
*/
#ifndef __IDE_DISK_HH__
#define __IDE_DISK_HH__
#include "base/statistics.hh"
#include "dev/disk_image.hh"
#include "dev/ide_atareg.h"
#include "dev/ide_ctrl.hh"
#include "dev/ide_wdcreg.h"
#include "dev/io_device.hh"
#include "sim/eventq.hh"
class ChunkGenerator;
#define DMA_BACKOFF_PERIOD 200
#define MAX_DMA_SIZE (131072) // 128K
#define MAX_MULTSECT (128)
#define PRD_BASE_MASK 0xfffffffe
#define PRD_COUNT_MASK 0xfffe
#define PRD_EOT_MASK 0x8000
typedef struct PrdEntry {
uint32_t baseAddr;
uint16_t byteCount;
uint16_t endOfTable;
} PrdEntry_t;
class PrdTableEntry {
public:
PrdEntry_t entry;
uint32_t getBaseAddr()
{
return (entry.baseAddr & PRD_BASE_MASK);
}
uint32_t getByteCount()
{
return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
(entry.byteCount & PRD_COUNT_MASK));
}
uint16_t getEOT()
{
return (entry.endOfTable & PRD_EOT_MASK);
}
};
#define DATA_OFFSET (0)
#define ERROR_OFFSET (1)
#define FEATURES_OFFSET (1)
#define NSECTOR_OFFSET (2)
#define SECTOR_OFFSET (3)
#define LCYL_OFFSET (4)
#define HCYL_OFFSET (5)
#define SELECT_OFFSET (6)
#define DRIVE_OFFSET (6)
#define STATUS_OFFSET (7)
#define COMMAND_OFFSET (7)
#define CONTROL_OFFSET (2)
#define ALTSTAT_OFFSET (2)
#define SELECT_DEV_BIT 0x10
#define CONTROL_RST_BIT 0x04
#define CONTROL_IEN_BIT 0x02
#define STATUS_BSY_BIT 0x80
#define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT 0x08
#define STATUS_SEEK_BIT 0x10
#define STATUS_DF_BIT 0x20
#define DRIVE_LBA_BIT 0x40
#define DEV0 (0)
#define DEV1 (1)
typedef struct CommandReg {
uint16_t data;
uint8_t error;
uint8_t sec_count;
uint8_t sec_num;
uint8_t cyl_low;
uint8_t cyl_high;
union {
uint8_t drive;
uint8_t head;
};
uint8_t command;
} CommandReg_t;
typedef enum Events {
None = 0,
Transfer,
ReadWait,
WriteWait,
PrdRead,
DmaRead,
DmaWrite
} Events_t;
typedef enum DevAction {
ACT_NONE = 0,
ACT_CMD_WRITE,
ACT_CMD_COMPLETE,
ACT_CMD_ERROR,
ACT_SELECT_WRITE,
ACT_STAT_READ,
ACT_DATA_READY,
ACT_DATA_READ_BYTE,
ACT_DATA_READ_SHORT,
ACT_DATA_WRITE_BYTE,
ACT_DATA_WRITE_SHORT,
ACT_DMA_READY,
ACT_DMA_DONE,
ACT_SRST_SET,
ACT_SRST_CLEAR
} DevAction_t;
typedef enum DevState {
// Device idle
Device_Idle_S = 0,
Device_Idle_SI,
Device_Idle_NS,
// Software reset
Device_Srst,
// Non-data commands
Command_Execution,
// PIO data-in (data to host)
Prepare_Data_In,
Data_Ready_INTRQ_In,
Transfer_Data_In,
// PIO data-out (data from host)
Prepare_Data_Out,
Data_Ready_INTRQ_Out,
Transfer_Data_Out,
// DMA protocol
Prepare_Data_Dma,
Transfer_Data_Dma
} DevState_t;
typedef enum DmaState {
Dma_Idle = 0,
Dma_Start,
Dma_Transfer
} DmaState_t;
class PhysicalMemory;
class IdeController;
/**
* IDE Disk device model
*/
class IdeDisk : public SimObject
{
protected:
/** The IDE controller for this disk. */
IdeController *ctrl;
/** The image that contains the data of this disk. */
DiskImage *image;
protected:
/** The disk delay in microseconds. */
int diskDelay;
private:
/** Drive identification structure for this disk */
struct ataparams driveID;
/** Data buffer for transfers */
uint8_t *dataBuffer;
/** Number of bytes in command data transfer */
uint32_t cmdBytes;
/** Number of bytes left in command data transfer */
uint32_t cmdBytesLeft;
/** Number of bytes left in DRQ block */
uint32_t drqBytesLeft;
/** Current sector in access */
uint32_t curSector;
/** Command block registers */
CommandReg_t cmdReg;
/** Status register */
uint8_t status;
/** Interrupt enable bit */
bool nIENBit;
/** Device state */
DevState_t devState;
/** Dma state */
DmaState_t dmaState;
/** Dma transaction is a read */
bool dmaRead;
/** PRD table base address */
uint32_t curPrdAddr;
/** PRD entry */
PrdTableEntry curPrd;
/** Device ID (master=0/slave=1) */
int devID;
/** Interrupt pending */
bool intrPending;
Stats::Scalar<> dmaReadFullPages;
Stats::Scalar<> dmaReadBytes;
Stats::Scalar<> dmaReadTxs;
Stats::Scalar<> dmaWriteFullPages;
Stats::Scalar<> dmaWriteBytes;
Stats::Scalar<> dmaWriteTxs;
Stats::Formula rdBandwidth;
Stats::Formula wrBandwidth;
Stats::Formula totBandwidth;
Stats::Formula totBytes;
public:
/**
* Create and initialize this Disk.
* @param name The name of this disk.
* @param img The disk image of this disk.
* @param id The disk ID (master=0/slave=1)
* @param disk_delay The disk delay in milliseconds
*/
IdeDisk(const std::string &name, DiskImage *img, int id, Tick disk_delay);
/**
* Delete the data buffer.
*/
~IdeDisk();
/**
* Reset the device state
*/
void reset(int id);
/**
* Register Statistics
*/
void regStats();
/**
* Set the controller for this device
* @param c The IDE controller
*/
void setController(IdeController *c) {
if (ctrl) panic("Cannot change the controller once set!\n");
ctrl = c;
}
// Device register read/write
void read(const Addr &offset, IdeRegType regtype, uint8_t *data);
void write(const Addr &offset, IdeRegType regtype, const uint8_t *data);
// Start/abort functions
void startDma(const uint32_t &prdTableBase);
void abortDma();
private:
void startCommand();
// Interrupt management
void intrPost();
void intrClear();
// DMA stuff
void doDmaTransfer();
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
void doDmaDataRead();
void doDmaRead();
ChunkGenerator *dmaReadCG;
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
void doDmaDataWrite();
void doDmaWrite();
ChunkGenerator *dmaWriteCG;
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
void dmaPrdReadDone();
friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;
void dmaReadDone();
friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;
void dmaWriteDone();
friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;
// Disk image read/write
void readDisk(uint32_t sector, uint8_t *data);
void writeDisk(uint32_t sector, uint8_t *data);
// State machine management
void updateState(DevAction_t action);
// Utility functions
bool isBSYSet() { return (status & STATUS_BSY_BIT); }
bool isIENSet() { return nIENBit; }
bool isDEVSelect();
void setComplete()
{
// clear out the status byte
status = 0;
// set the DRDY bit
status |= STATUS_DRDY_BIT;
// set the SEEK bit
status |= STATUS_SEEK_BIT;
}
uint32_t getLBABase()
{
return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
(cmdReg.cyl_low << 8) | (cmdReg.sec_num));
}
inline Addr pciToDma(Addr pciAddr);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint to use.
* @param section The section name describing this object.
*/
void unserialize(Checkpoint *cp, const std::string &section);
};
#endif // __IDE_DISK_HH__