57#include "debug/IdeDisk.hh"
70 dmaReadWaitEvent([
this]{ doDmaRead(); },
name()),
71 dmaWriteWaitEvent([
this]{ doDmaWrite(); },
name()),
72 dmaPrdReadEvent([
this]{ dmaPrdReadDone(); },
name()),
73 dmaReadEvent([
this]{ dmaReadDone(); },
name()),
74 dmaWriteEvent([
this]{ dmaWriteDone(); },
name())
80 memset(&driveID, 0,
sizeof(
struct ataparams));
87 uint32_t lba_size = image->size();
88 if (lba_size >= 16383*16*63) {
95 else if (lba_size == 0)
96 panic(
"Bad IDE image size: 0\n");
100 if ((lba_size / sectors) >= 16)
103 heads = (lba_size / sectors);
105 cylinders = lba_size / (heads * sectors);
109 strncpy((
char *)driveID.atap_model,
"5MI EDD si k",
110 sizeof(driveID.atap_model));
114 driveID.atap_capabilities1 = 0x7;
116 driveID.atap_extensions = 0x6;
118 driveID.atap_cylinders = cylinders;
119 driveID.atap_sectors = sectors;
120 driveID.atap_heads = heads;
123 driveID.atap_curmulti_valid = 0x1;
125 driveID.atap_capacity = lba_size;
127 driveID.atap_dmamode_supp = 0x4;
129 driveID.atap_piomode_supp = 0x3;
131 driveID.atap_udmamode_supp = 0x1f;
133 driveID.atap_hwreset_res = 0x4001;
172 }
else if (
id ==
DEV1) {
176 panic(
"Invalid device ID: %#x\n",
id);
194 return channel->selected() ==
this;
201 return ctrl->pciToDma(pciAddr);
212 if (size ==
sizeof(uint16_t)) {
214 }
else if (size ==
sizeof(uint32_t)) {
219 panic(
"Data read of unsupported size %d.\n", size);
224 assert(size ==
sizeof(uint8_t));
249 panic(
"Invalid IDE command register offset: %#x\n",
offset);
257 assert(size ==
sizeof(uint8_t));
260 panic(
"Invalid IDE control register offset: %#x\n",
offset);
268 if (size ==
sizeof(uint16_t)) {
270 }
else if (size ==
sizeof(uint32_t)) {
275 panic(
"Data write of unsupported size %d.\n", size);
281 assert(size ==
sizeof(uint8_t));
306 panic(
"Invalid IDE command register offset: %#x\n",
offset);
316 panic(
"Invalid IDE control register offset: %#x\n",
offset);
346 panic(
"Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
369 "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
399 "Number of full page size DMA reads (not PRD)."),
401 "Number of bytes transfered via DMA reads (not PRD)."),
403 "Number of DMA read transactions (not PRD)."),
405 "Number of full page size DMA writes."),
407 "Number of bytes transfered via DMA writes."),
409 "Number of DMA write transactions.")
455 uint32_t bytesWritten = 0;
458 for (bytesWritten = 0; bytesWritten <
curPrd.getByteCount();
480 uint32_t bytesRead = 0;
482 DPRINTF(
IdeDisk,
"doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
487 while (bytesRead <
curPrd.getByteCount()) {
522 DPRINTF(
IdeDisk,
"doDmaWrite: not done curPrd byte count %d, eot %#x\n",
530 DPRINTF(
IdeDisk,
"doDmaWrite: done curPrd byte count %d, eot %#x\n",
543 "doWriteDone: curPrd byte count %d, eot %#x cmd bytes left:%d\n",
562 uint32_t bytesRead =
image->read(
data, sector);
565 "Can't read from %s. Only %d of %d read. errno=%d",
572 uint32_t bytesWritten =
image->write(
data, sector);
575 "Can't write to %s. Only %d of %d written. errno=%d",
587 "Inconsistent DMA state, should be in Dma_Start!");
590 "Inconsistent device state for DMA start!");
605 "Inconsistent DMA state, should be Start or Transfer!");
608 "Inconsistent device state, should be Transfer or Prepare!");
628 size = (uint32_t)
image->size() - 1;
629 cmdReg.sec_num = (size & 0xff);
630 cmdReg.cyl_low = ((size & 0xff00) >> 8);
631 cmdReg.cyl_high = ((size & 0xff0000) >> 16);
632 cmdReg.head = ((size & 0xf000000) >> 24);
669 "Attempt to perform CHS access, only supports LBA");
671 if (
cmdReg.sec_count == 0)
687 "Attempt to perform CHS access, only supports LBA");
689 if (
cmdReg.sec_count == 0)
706 "Attempt to perform CHS access, only supports LBA");
708 if (
cmdReg.sec_count == 0)
722 panic(
"Unsupported ATA command: %#x\n",
cmdReg.command);
746 "Attempt to post an interrupt with one pending");
891 panic(
"DEBUG: READING DATA ONE BYTE AT A TIME!\n");
898 memcpy((
void *)&
cmdReg.data,
967 panic(
"DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
1018 panic(
"Inconsistent DMA state, should be Dma_Idle\n");
1061 DPRINTF(
IdeDisk,
"Disk still busy aborting previous DMA command\n");
1078 [[maybe_unused]]
int eventCount = 0;
1111 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...
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
#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.
@ Running
Running normally.
void schedule(Event &event, Tick when)
void reschedule(Event &event, Tick when, bool always=false)
#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)
SimObject(const Params &p)
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 Arm Limited 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()