Add the capability to iterate through the packets in a pktfifo,
[gem5.git] / dev / pcidev.hh
index c0fe47ac4461d54ba3255b368c14d0490c076d60..efc805b3f3c7d5956c3c5a4a3f53d02da0ae2655 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 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
  * Interface for devices using PCI configuration
  */
 
-#ifndef __PCI_DEV_HH__
-#define __PCI_DEV_HH__
+#ifndef __DEV_PCIDEV_HH__
+#define __DEV_PCIDEV_HH__
 
-#include "dev/pcireg.h"
 #include "dev/io_device.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
+
+#define BAR_IO_MASK 0x3
+#define BAR_MEM_MASK 0xF
+#define BAR_IO_SPACE_BIT 0x1
+#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
+#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
 
 class PciConfigAll;
 class MemoryController;
@@ -77,30 +84,45 @@ class PciConfigData : public SimObject
  */
 class PciDev : public DmaDevice
 {
-  protected:
-    MemoryController *mmu;
-    /** A pointer to the configspace all object that calls
-     * us when a read comes to this particular device/function.
-     */
-    PciConfigAll *configSpace;
+  public:
+    struct Params
+    {
+        std::string name;
+        Platform *plat;
+        MemoryController *mmu;
 
-    /**
-     * A pointer to the object that contains the first 64 bytes of
-     * config space
-     */
-    PciConfigData *configData;
+        /**
+         * A pointer to the configspace all object that calls us when
+         * a read comes to this particular device/function.
+         */
+        PciConfigAll *configSpace;
+
+        /**
+         * A pointer to the object that contains the first 64 bytes of
+         * config space
+         */
+        PciConfigData *configData;
 
-    /** The bus number we are on */
-    uint32_t busNum;
+        /** The bus number we are on */
+        uint32_t busNum;
 
-    /** The device number we have */
-    uint32_t deviceNum;
+        /** The device number we have */
+        uint32_t deviceNum;
 
-    /** The function number */
-    uint32_t functionNum;
+        /** The function number */
+        uint32_t functionNum;
+    };
 
-    /** The current config space. Unlike the PciConfigData this is updated
-     * during simulation while continues to refelect what was in the config file.
+  protected:
+    Params *_params;
+
+  public:
+    const Params *params() const { return _params; }
+
+  protected:
+    /** The current config space. Unlike the PciConfigData this is
+     * updated during simulation while continues to reflect what was
+     * in the config file.
      */
     PCIConfig config;
 
@@ -110,29 +132,96 @@ class PciDev : public DmaDevice
     /** The current address mapping of the BARs */
     Addr BARAddrs[6];
 
+    bool
+    isBAR(Addr addr, int bar) const
+    {
+        assert(bar >= 0 && bar < 6);
+        return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar];
+    }
+
+    int
+    getBAR(Addr addr)
+    {
+        for (int i = 0; i <= 5; ++i)
+            if (isBAR(addr, i))
+                return i;
+
+        return -1;
+    }
+
+    bool
+    getBAR(Addr paddr, Addr &daddr, int &bar)
+    {
+        int b = getBAR(paddr);
+        if (b < 0)
+            return false;
+
+        daddr = paddr - BARAddrs[b];
+        bar = b;
+        return true;
+    }
+
+  protected:
+    Platform *plat;
+    PciConfigData *configData;
+
+  public:
+    Addr pciToDma(Addr pciAddr) const
+    { return plat->pciToDma(pciAddr); }
+
+    void
+    intrPost()
+    { plat->postPciInt(configData->config.interruptLine); }
+
+    void
+    intrClear()
+    { plat->clearPciInt(configData->config.interruptLine); }
+
+    uint8_t
+    interruptLine()
+    { return configData->config.interruptLine; }
+
   public:
     /**
-     * Constructor for PCI Dev. This function copies data from the config file
-     * object PCIConfigData and registers the device with a PciConfigAll object.
-     * @param name name of the object
-     * @param mmu a pointer to the memory controller
-     * @param cf a pointer to the config space object that this device need to
-     *           register with
-     * @param cd A pointer to the config space values specified in the conig file
-     * @param bus the bus this device is on
-     * @param dev the device id of this device
-     * @param func the function number of this device
+     * Constructor for PCI Dev. This function copies data from the
+     * config file object PCIConfigData and registers the device with
+     * a PciConfigAll object.
      */
-    PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf,
-           PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func);
+    PciDev(Params *params);
 
-    virtual Fault read(MemReqPtr &req, uint8_t *data) {
-        return No_Fault;
-    }
-    virtual Fault write(MemReqPtr &req, const uint8_t *data) {
-        return No_Fault;
-    }
+    virtual Fault read(MemReqPtr &req, uint8_t *data);
+    virtual Fault write(MemReqPtr &req, const uint8_t *data);
 
+  public:
+    /**
+     * Implement the read/write as BAR accesses
+     */
+    Fault readBar(MemReqPtr &req, uint8_t *data);
+    Fault writeBar(MemReqPtr &req, const uint8_t *data);
+
+  public:
+    /**
+     * Read from a specific BAR
+     */
+    virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
+    virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data);
+    virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data);
+    virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data);
+    virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data);
+    virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data);
+
+  public:
+    /**
+     * Write to a specific BAR
+     */
+    virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
+    virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data);
+    virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data);
+    virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data);
+    virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data);
+    virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data);
+
+  public:
     /**
      * Write to the PCI config space data that is stored locally. This may be
      * overridden by the device but at some point it will eventually call this
@@ -141,7 +230,7 @@ class PciDev : public DmaDevice
      * @param size the size of the write
      * @param data the data to write
      */
-    virtual void WriteConfig(int offset, int size, uint32_t data);
+    virtual void writeConfig(int offset, int size, const uint8_t* data);
 
 
     /**
@@ -152,7 +241,7 @@ class PciDev : public DmaDevice
      * @param size the size of the read
      * @param data pointer to the location where the read value should be stored
      */
-    virtual void ReadConfig(int offset, int size, uint8_t *data);
+    virtual void readConfig(int offset, int size, uint8_t *data);
 
     /**
      * Serialize this object to the given output stream.
@@ -168,4 +257,40 @@ class PciDev : public DmaDevice
     virtual void unserialize(Checkpoint *cp, const std::string &section);
 };
 
-#endif // __PCI_DEV_HH__
+inline Fault
+PciDev::readBar(MemReqPtr &req, uint8_t *data)
+{
+    if (isBAR(req->paddr, 0))
+        return readBar0(req, req->paddr - BARAddrs[0], data);
+    if (isBAR(req->paddr, 1))
+        return readBar1(req, req->paddr - BARAddrs[1], data);
+    if (isBAR(req->paddr, 2))
+        return readBar2(req, req->paddr - BARAddrs[2], data);
+    if (isBAR(req->paddr, 3))
+        return readBar3(req, req->paddr - BARAddrs[3], data);
+    if (isBAR(req->paddr, 4))
+        return readBar4(req, req->paddr - BARAddrs[4], data);
+    if (isBAR(req->paddr, 5))
+        return readBar5(req, req->paddr - BARAddrs[5], data);
+    return Machine_Check_Fault;
+}
+
+inline Fault
+PciDev::writeBar(MemReqPtr &req, const uint8_t *data)
+{
+    if (isBAR(req->paddr, 0))
+        return writeBar0(req, req->paddr - BARAddrs[0], data);
+    if (isBAR(req->paddr, 1))
+        return writeBar1(req, req->paddr - BARAddrs[1], data);
+    if (isBAR(req->paddr, 2))
+        return writeBar2(req, req->paddr - BARAddrs[2], data);
+    if (isBAR(req->paddr, 3))
+        return writeBar3(req, req->paddr - BARAddrs[3], data);
+    if (isBAR(req->paddr, 4))
+        return writeBar4(req, req->paddr - BARAddrs[4], data);
+    if (isBAR(req->paddr, 5))
+        return writeBar5(req, req->paddr - BARAddrs[5], data);
+    return Machine_Check_Fault;
+}
+
+#endif // __DEV_PCIDEV_HH__