/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * 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
#ifndef __IDE_DISK_HH__
#define __IDE_DISK_HH__
-#include "dev/ide.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"
#define DMA_BACKOFF_PERIOD 200
-#define MAX_DMA_SIZE (131072) // 256 * SectorSize (512)
-#define MAX_MULTSECT (128)
+#define MAX_DMA_SIZE (65536) // 64K
+#define MAX_MULTSECT (128)
#define PRD_BASE_MASK 0xfffffffe
#define PRD_COUNT_MASK 0xfffe
return (entry.baseAddr & PRD_BASE_MASK);
}
- uint16_t getByteCount()
+ uint32_t getByteCount()
{
return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
(entry.byteCount & PRD_COUNT_MASK));
#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 STATUS_BSY_BIT 0x80
#define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT 0x08
-#define DRIVE_LBA_BIT 0x40
+#define STATUS_SEEK_BIT 0x10
+#define STATUS_DF_BIT 0x20
+#define DRIVE_LBA_BIT 0x40
#define DEV0 (0)
#define DEV1 (1)
typedef struct CommandReg {
- uint8_t data0;
- union {
- uint8_t data1;
- uint8_t error;
- uint8_t features;
- };
+ uint16_t data;
+ uint8_t error;
uint8_t sec_count;
uint8_t sec_num;
uint8_t cyl_low;
uint8_t drive;
uint8_t head;
};
- union {
- uint8_t status;
- uint8_t command;
- };
+ 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_WRITE_BYTE,
ACT_DATA_WRITE_SHORT,
ACT_DMA_READY,
- ACT_DMA_DONE
+ ACT_DMA_DONE,
+ ACT_SRST_SET,
+ ACT_SRST_CLEAR
} DevAction_t;
typedef enum DevState {
Device_Idle_SI,
Device_Idle_NS,
+ // Software reset
+ Device_Srst,
+
// Non-data commands
Command_Execution,
PhysicalMemory *physmem;
protected:
- /** The disk delay in milliseconds. */
+ /** The disk delay in microseconds. */
int diskDelay;
private:
/** Drive identification structure for this disk */
- struct hd_driveid driveID;
+ 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 curSector;
/** Command block registers */
CommandReg_t cmdReg;
- /** Shadow of the current command code */
- uint8_t curCommand;
+ /** Status register */
+ uint8_t status;
/** Interrupt enable bit */
bool nIENBit;
/** Device state */
uint32_t curPrdAddr;
/** PRD entry */
PrdTableEntry curPrd;
+ /** Number of bytes transfered by DMA interface for current transfer */
+ uint32_t dmaInterfaceBytes;
/** Device ID (master=0/slave=1) */
int devID;
/** Interrupt pending */
* @param disk_delay The disk delay in milliseconds
*/
IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys,
- int id, int disk_delay);
+ int id, Tick disk_delay);
/**
* Delete the data buffer.
*/
~IdeDisk();
+ /**
+ * Reset the device state
+ */
+ void reset(int id);
+
/**
* Set the controller for this device
* @param c The IDE controller
}
// Device register read/write
- void read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data);
- void write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data);
+ 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 updateState(DevAction_t action);
// Utility functions
- bool isBSYSet() { return (cmdReg.status & STATUS_BSY_BIT); }
+ bool isBSYSet() { return (status & STATUS_BSY_BIT); }
bool isIENSet() { return nIENBit; }
- bool isDEVSelect() { return ((cmdReg.drive & SELECT_DEV_BIT) == devID); }
+ bool isDEVSelect();
void setComplete()
{
// clear out the status byte
- cmdReg.status = 0;
-
+ status = 0;
// set the DRDY bit
- cmdReg.status |= STATUS_DRDY_BIT;
+ status |= STATUS_DRDY_BIT;
+ // set the SEEK bit
+ status |= STATUS_SEEK_BIT;
}
uint32_t getLBABase()
(cmdReg.cyl_low << 8) | (cmdReg.sec_num));
}
+ inline Addr pciToDma(Addr pciAddr);
+
+ uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft);
+
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.