Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5
[gem5.git] / dev / ide_ctrl.hh
index ac25eafe7fc890ca10b33214b14929d41aca5c76..b29e5ae9a1d3bc797b18e3f374d287ff07321670 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,8 @@
  */
 
 /** @file
- * Simple PCI IDE controller with bus mastering capability
+ * Simple PCI IDE controller with bus mastering capability and UDMA
+ * modeled after controller in the Intel PIIX4 chip
  */
 
 #ifndef __IDE_CTRL_HH__
 #include "dev/pcireg.h"
 #include "dev/io_device.hh"
 
-#define CMD0  0x00 // Channel 0 command block offset
-#define CTRL0 0x08 // Channel 0 control block offset
-#define CMD1  0x0c // Channel 1 command block offset
-#define CTRL1 0x14 // Channel 1 control block offset
-#define BMI   0x18 // Bus master IDE offset
-
 #define BMIC0    0x0  // Bus master IDE command register
 #define BMIS0    0x2  // Bus master IDE status register
 #define BMIDTP0  0x4  // Bus master IDE descriptor table pointer register
 #define BMIDEA  0x01 // Bus master IDE active
 
 // IDE Command byte fields
-// Taken from include/linux/ide.h
-#define IDE_DATA_OFFSET         (0)
-#define IDE_ERROR_OFFSET        (1)
-#define IDE_NSECTOR_OFFSET      (2)
-#define IDE_SECTOR_OFFSET       (3)
-#define IDE_LCYL_OFFSET         (4)
-#define IDE_HCYL_OFFSET         (5)
 #define IDE_SELECT_OFFSET       (6)
-#define IDE_STATUS_OFFSET       (7)
-#define IDE_CONTROL_OFFSET      (8)
-#define IDE_IRQ_OFFSET          (9)
+#define IDE_SELECT_DEV_BIT      0x10
 
 #define IDE_FEATURE_OFFSET      IDE_ERROR_OFFSET
 #define IDE_COMMAND_OFFSET      IDE_STATUS_OFFSET
 #define UDMACTL (5)
 #define UDMATIM (6)
 
-// PCI Command bit fields
-#define BME     0x04 // Bus master function enable
-#define IOSE    0x01 // I/O space enable
+typedef enum RegType {
+    COMMAND_BLOCK = 0,
+    CONTROL_BLOCK,
+    BMI_BLOCK
+} RegType_t;
 
-class IntrControl;
 class IdeDisk;
+class IntrControl;
 class PciConfigAll;
 class Tsunami;
 class PhysicalMemory;
@@ -125,8 +113,10 @@ class IdeController : public PciDev
     Addr bmi_size;
 
   private:
-    /** Registers used for programmed I/O and bus master interface */
-    uint8_t regs[40];
+    /** Registers used for bus master interface */
+    uint8_t bmi_regs[16];
+    /** Shadows of the device select bit */
+    uint8_t dev[2];
     /** Registers used in PCI configuration */
     uint8_t pci_regs[8];
 
@@ -135,59 +125,28 @@ class IdeController : public PciDev
     bool bm_enabled;
     bool cmd_in_progress[4];
 
-  private:
+  public:
     /** Pointer to the chipset */
     Tsunami *tsunami;
+
+  private:
     /** IDE disks connected to controller */
     IdeDisk *disks[4];
 
   private:
-    /** Get offset into register file from access address */
-    Addr getOffset(const Addr &addr) {
-        Addr offset = addr;
-
-        if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
-            offset -= pri_cmd_addr;
-            offset += CMD0;
-        } else if (addr >= pri_ctrl_addr &&
-                   addr < (pri_ctrl_addr + pri_ctrl_size)) {
-            offset -= pri_ctrl_addr;
-            offset += CTRL0;
-        } else if (addr >= sec_cmd_addr &&
-                   addr < (sec_cmd_addr + sec_cmd_size)) {
-            offset -= sec_cmd_addr;
-            offset += CMD1;
-        } else if (addr >= sec_ctrl_addr &&
-                   addr < (sec_ctrl_addr + sec_ctrl_size)) {
-            offset -= sec_ctrl_addr;
-            offset += CTRL1;
-        } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
-            offset -= bmi_addr;
-            offset += BMI;
-        } else {
-            panic("IDE controller access to invalid address: %#x\n", addr);
-        }
-
-        return offset;
-    };
-    /** Select the disk based on the register offset */
-    int getDisk(const Addr &offset) {
-        int disk = 0;
-
-        // If the offset is in the channel 1 range, disks are 2 or 3
-        if (offset >= CMD1 && offset < BMI && offset >= (BMI + BMIC1))
-            disk += 2;
-
-        if (disk < 2) {
-            if (regs[CMD0 + IDE_STATUS_OFFSET] & 0x10)
-                disk += 1;
-        } else {
-            if (regs[CMD1 + IDE_STATUS_OFFSET] & 0x10)
-                disk += 1;
-        }
-
-        return disk;
-    };
+    /** Parse the access address to pass on to device */
+    void parseAddr(const Addr &addr, Addr &offset, bool &primary,
+                   RegType_t &type);
+
+    /** Select the disk based on the channel and device bit */
+    int getDisk(bool primary);
+
+    /** Select the disk based on a pointer */
+    int getDisk(IdeDisk *diskPtr);
+
+  public:
+    /** See if a disk is selected based on its pointer */
+    bool isDiskSelected(IdeDisk *diskPtr);
 
   public:
     /**
@@ -204,11 +163,11 @@ class IdeController : public PciDev
      * @param hier The hierarchy parameters
      */
     IdeController(const std::string &name, IntrControl *ic,
-                  const vector<IdeDisk *> &new_disks,
+                  const std::vector<IdeDisk *> &new_disks,
                   MemoryController *mmu, PciConfigAll *cf,
                   PciConfigData *cd, Tsunami *t,
                   uint32_t bus_num, uint32_t dev_num, uint32_t func_num,
-                  Bus *host_bus, HierParams *hier);
+                  Bus *host_bus, Tick pio_latency, HierParams *hier);
 
     /**
      * Deletes the connected devices.
@@ -218,6 +177,11 @@ class IdeController : public PciDev
     virtual void WriteConfig(int offset, int size, uint32_t data);
     virtual void ReadConfig(int offset, int size, uint8_t *data);
 
+    void intrPost();
+    void intrClear();
+
+    void setDmaComplete(IdeDisk *disk);
+
     /**
      * Read a done field for a given target.
      * @param req Contains the address of the field to read.
@@ -234,12 +198,6 @@ class IdeController : public PciDev
      */
     virtual Fault write(MemReqPtr &req, const uint8_t *data);
 
-    /**
-     * Cache access timing specific to device
-     * @param req Memory request
-     */
-    Tick cacheAccess(MemReqPtr &req);
-
     /**
      * Serialize this object to the given output stream.
      * @param os The stream to serialize to.
@@ -253,5 +211,11 @@ class IdeController : public PciDev
      */
     virtual void unserialize(Checkpoint *cp, const std::string &section);
 
+    /**
+     * Return how long this access will take.
+     * @param req the memory request to calcuate
+     * @return Tick when the request is done
+     */
+    Tick cacheAccess(MemReqPtr &req);
 };
 #endif // __IDE_CTRL_HH_