only set an approriately sized piece of data. so break where appropriate
[gem5.git] / dev / ide_disk.hh
index 016f827cc769bbb327d103ca95dce56bd1ecf6eb..a656ca464ef8c14ae52a5480fa0ecc9800ffbf60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -62,7 +64,7 @@ class PrdTableEntry {
         return (entry.baseAddr & PRD_BASE_MASK);
     }
 
-    uint16_t getByteCount()
+    uint32_t getByteCount()
     {
         return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
                 (entry.byteCount & PRD_COUNT_MASK));
@@ -82,6 +84,7 @@ class PrdTableEntry {
 #define LCYL_OFFSET     (4)
 #define HCYL_OFFSET     (5)
 #define SELECT_OFFSET   (6)
+#define DRIVE_OFFSET    (6)
 #define STATUS_OFFSET   (7)
 #define COMMAND_OFFSET  (7)
 
@@ -94,18 +97,16 @@ class PrdTableEntry {
 #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;
@@ -114,17 +115,25 @@ typedef struct CommandReg {
         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,
@@ -132,7 +141,9 @@ typedef enum DevAction {
     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 {
@@ -141,6 +152,9 @@ typedef enum DevState {
     Device_Idle_SI,
     Device_Idle_NS,
 
+    // Software reset
+    Device_Srst,
+
     // Non-data commands
     Command_Execution,
 
@@ -184,14 +198,16 @@ class IdeDisk : public SimObject
     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 */
@@ -200,8 +216,8 @@ class IdeDisk : public SimObject
     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 */
@@ -214,6 +230,8 @@ class IdeDisk : public SimObject
     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 */
@@ -229,13 +247,18 @@ class IdeDisk : public SimObject
      * @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
@@ -247,8 +270,8 @@ class IdeDisk : public SimObject
     }
 
     // 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);
@@ -294,17 +317,18 @@ class IdeDisk : public SimObject
     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()
@@ -313,6 +337,10 @@ class IdeDisk : public SimObject
                        (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.