57#include "debug/IdeDisk.hh"
67 :
SimObject(
p), image(
p.image), diskDelay(
p.delay), ideDiskStats(this),
69 dmaReadWaitEvent([
this]{ doDmaRead(); },
name()),
70 dmaWriteWaitEvent([
this]{ doDmaWrite(); },
name()),
71 dmaPrdReadEvent([
this]{ dmaPrdReadDone(); },
name()),
72 dmaReadEvent([
this]{ dmaReadDone(); },
name()),
73 dmaWriteEvent([
this]{ dmaWriteDone(); },
name())
79 memset(&driveID, 0,
sizeof(
struct ataparams));
86 uint32_t lba_size = image->size();
87 if (lba_size >= 16383*16*63) {
94 else if (lba_size == 0)
95 panic(
"Bad IDE image size: 0\n");
99 if ((lba_size / sectors) >= 16)
102 heads = (lba_size / sectors);
104 cylinders = lba_size / (heads * sectors);
108 strncpy((
char *)driveID.atap_model,
"5MI EDD si k",
109 sizeof(driveID.atap_model));
113 driveID.atap_capabilities1 = 0x7;
115 driveID.atap_extensions = 0x6;
117 driveID.atap_cylinders = cylinders;
118 driveID.atap_sectors = sectors;
119 driveID.atap_heads = heads;
122 driveID.atap_curmulti_valid = 0x1;
124 driveID.atap_capacity = lba_size;
126 driveID.atap_dmamode_supp = 0x4;
128 driveID.atap_piomode_supp = 0x3;
130 driveID.atap_udmamode_supp = 0x1f;
132 driveID.atap_hwreset_res = 0x4001;
169 }
else if (
id ==
DEV1) {
173 panic(
"Invalid device ID: %#x\n",
id);
209 if (size ==
sizeof(uint16_t)) {
211 }
else if (size ==
sizeof(uint32_t)) {
216 panic(
"Data read of unsupported size %d.\n", size);
221 assert(size ==
sizeof(uint8_t));
246 panic(
"Invalid IDE command register offset: %#x\n",
offset);
254 assert(size ==
sizeof(uint8_t));
257 panic(
"Invalid IDE control register offset: %#x\n",
offset);
265 if (size ==
sizeof(uint16_t)) {
267 }
else if (size ==
sizeof(uint32_t)) {
272 panic(
"Data write of unsupported size %d.\n", size);
278 assert(size ==
sizeof(uint8_t));
303 panic(
"Invalid IDE command register offset: %#x\n",
offset);
313 panic(
"Invalid IDE control register offset: %#x\n",
offset);
343 panic(
"Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
366 "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
394 : statistics::
Group(parent,
"IdeDisk"),
395 ADD_STAT(dmaReadFullPages, statistics::units::Count::get(),
396 "Number of full page size DMA reads (not PRD)."),
397 ADD_STAT(dmaReadBytes, statistics::units::Byte::get(),
398 "Number of bytes transfered via DMA reads (not PRD)."),
399 ADD_STAT(dmaReadTxs, statistics::units::Count::get(),
400 "Number of DMA read transactions (not PRD)."),
401 ADD_STAT(dmaWriteFullPages, statistics::units::Count::get(),
402 "Number of full page size DMA writes."),
403 ADD_STAT(dmaWriteBytes, statistics::units::Byte::get(),
404 "Number of bytes transfered via DMA writes."),
405 ADD_STAT(dmaWriteTxs, statistics::units::Count::get(),
406 "Number of DMA write transactions.")
452 uint32_t bytesWritten = 0;
477 uint32_t bytesRead = 0;
479 DPRINTF(
IdeDisk,
"doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
519 DPRINTF(
IdeDisk,
"doDmaWrite: not done curPrd byte count %d, eot %#x\n",
527 DPRINTF(
IdeDisk,
"doDmaWrite: done curPrd byte count %d, eot %#x\n",
540 "doWriteDone: curPrd byte count %d, eot %#x cmd bytes left:%d\n",
562 "Can't read from %s. Only %d of %d read. errno=%d",
572 "Can't write to %s. Only %d of %d written. errno=%d",
584 "Inconsistent DMA state, should be in Dma_Start!");
587 "Inconsistent device state for DMA start!");
602 "Inconsistent DMA state, should be Start or Transfer!");
605 "Inconsistent device state, should be Transfer or Prepare!");
666 "Attempt to perform CHS access, only supports LBA");
684 "Attempt to perform CHS access, only supports LBA");
703 "Attempt to perform CHS access, only supports LBA");
726 status &= ~STATUS_DRQ_BIT;
743 "Attempt to post an interrupt with one pending");
777 status &= ~STATUS_BSY_BIT;
846 status &= ~STATUS_BSY_BIT;
888 panic(
"DEBUG: READING DATA ONE BYTE AT A TIME!\n");
910 status &= ~STATUS_DRQ_BIT;
933 status &= ~STATUS_BSY_BIT;
964 panic(
"DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
984 status &= ~STATUS_DRQ_BIT;
1008 status &= ~STATUS_BSY_BIT;
1015 panic(
"Inconsistent DMA state, should be Dma_Idle\n");
1058 DPRINTF(
IdeDisk,
"Disk still busy aborting previous DMA command\n");
1075 [[maybe_unused]]
int eventCount = 0;
1108 assert(eventCount <= 1);
Declaration and inline definition of ChunkGenerator object.
This class takes an arbitrary memory region (address/length pair) and generates a series of appropria...
virtual std::streampos write(const uint8_t *data, std::streampos offset)=0
virtual std::streampos size() const =0
virtual std::streampos read(uint8_t *data, std::streampos offset) const =0
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
IdeDisk * selected() const
EventFunctionWrapper dmaReadEvent
uint32_t drqBytesLeft
Number of bytes left in DRQ block.
EventFunctionWrapper dmaPrdReadEvent
void startDma(const uint32_t &prdTableBase)
void serialize(CheckpointOut &cp) const override
Serialize an object.
~IdeDisk()
Delete the data buffer.
void writeDisk(uint32_t sector, uint8_t *data)
bool nIENBit
Interrupt enable bit.
uint32_t cmdBytes
Number of bytes in command data transfer.
void readControl(const Addr offset, int size, uint8_t *data)
IdeController * ctrl
The IDE controller for this disk.
void writeCommand(const Addr offset, int size, const uint8_t *data)
uint32_t curPrdAddr
PRD table base address.
struct ataparams driveID
Drive identification structure for this disk.
uint8_t * dataBuffer
Data buffer for transfers.
ChunkGenerator * dmaWriteCG
PrdTableEntry curPrd
PRD entry.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
EventFunctionWrapper dmaWriteEvent
uint32_t curSector
Current sector in access.
bool dmaRead
Dma transaction is a read.
bool pendingInterrupt
Interrupt pending.
DiskImage * image
The image that contains the data of this disk.
EventFunctionWrapper dmaWriteWaitEvent
void reset(int id)
Reset the device state.
gem5::IdeDisk::IdeDiskStats ideDiskStats
ChunkGenerator * dmaReadCG
void readDisk(uint32_t sector, uint8_t *data)
DevState_t devState
Device state.
int diskDelay
The disk delay in microseconds.
EventFunctionWrapper dmaTransferEvent
void writeControl(const Addr offset, int size, const uint8_t *data)
bool dmaAborted
DMA Aborted.
uint8_t status
Status register.
Addr pciToDma(Addr pciAddr)
Addr chunkBytes
Size of chunks to DMA.
IdeController::Channel * channel
The channel this disk is connected to.
DmaState_t dmaState
Dma state.
void readCommand(const Addr offset, int size, uint8_t *data)
uint32_t cmdBytesLeft
Number of bytes left in command data transfer.
EventFunctionWrapper dmaReadWaitEvent
CommandReg_t cmdReg
Command block registers.
int devID
Device ID (device0=0/device1=1)
void updateState(DevAction_t action)
virtual std::string name() const
Addr pciToDma(Addr pci_addr) const
Abstract superclass for simulation objects.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Addr addr() const
Return starting address of current chunk.
Addr complete() const
Number of bytes we have already chunked up.
bool done() const
Are we done? That is, did the last call to next() advance past the end of the region?
Addr size() const
Return size in bytes of current chunk.
bool next()
Advance generator to next chunk.
DrainState drainState() const
Return the current drain state of an object.
@ Running
Running normally.
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
void reschedule(Event &event, Tick when, bool always=false)
Tick when() const
Get the time that the event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define SERIALIZE_ENUM(scalar)
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
#define UNSERIALIZE_ENUM(scalar)
Device model for an IDE disk.
#define DMA_BACKOFF_PERIOD
#define WDSF_READ_NATIVE_MAX
#define ATAPI_IDENTIFY_DEVICE
#define WDCC_STANDBY_IMMED
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
uint64_t Tick
Tick count type.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
Simple PCI IDE controller with bus mastering capability and UDMA modeled after controller in the Inte...
statistics::Scalar dmaWriteTxs
statistics::Scalar dmaWriteBytes
IdeDiskStats(statistics::Group *parent)
statistics::Scalar dmaWriteFullPages
statistics::Scalar dmaReadBytes
statistics::Scalar dmaReadFullPages
statistics::Scalar dmaReadTxs
const std::string & name()