summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
Diffstat (limited to 'dev')
-rw-r--r--dev/pcidev.cc23
-rw-r--r--dev/pcidev.hh8
2 files changed, 25 insertions, 6 deletions
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index 3fb47b46f..fcd011123 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -52,9 +52,10 @@ using namespace std;
PciDev::PciDev(const string &name, PCIConfigAll *cf, uint32_t bus,
uint32_t dev, uint32_t func)
- : MMapDevice(name), ConfigSpace(cf), Bus(bus), Device(dev), Function(func)
+ : MMapDevice(name), ConfigSpace(cf), Bus(bus), Device(dev), Function(func), MMU(mmu)
{
memset(config.data, 0, sizeof(config.data));
+ memset(BARAddrs, 0, sizeof(Addr) * 6);
// Setup pointer in config space to point to this entry
if(cf->devices[dev][func] != NULL)
@@ -93,6 +94,8 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
void
PciDev::WriteConfig(int offset, int size, uint32_t data)
{
+ uint32_t barnum;
+
union {
uint8_t byte_value;
uint16_t half_value;
@@ -103,6 +106,8 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
DPRINTF(PCIDEV, "write device: %#x function: %#x register: %#x size: %#x data: %#x\n",
Device, Function, offset, size, word_value);
+ barnum = (offset - PCI0_BASE_ADDR0) >> 2;
+
switch (size) {
case sizeof(uint8_t): // 1-byte access
switch (offset) {
@@ -146,11 +151,13 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
// This is I/O Space, bottom two bits are read only
if(config.data[offset] & 0x1) {
*(uint32_t *)&config.data[offset] =
- ~(BARSize[offset-PCI0_BASE_ADDR0] - 1) | (config.data[offset] & 0x3);
+ ~(BARSize[barnum] - 1) |
+ (config.data[offset] & 0x3);
} else {
// This is memory space, bottom four bits are read only
*(uint32_t *)&config.data[offset] =
- ~(BARSize[(offset-PCI0_BASE_ADDR0)>>2] - 1) | (config.data[offset] & 0xF);
+ ~(BARSize[barnum] - 1) |
+ (config.data[offset] & 0xF);
}
@@ -159,6 +166,16 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
if(config.data[offset] & 0x1) {
*(uint32_t *)&config.data[offset] = (word_value & ~0x3) |
(config.data[offset] & 0x3);
+ if (word_value) {
+ // It's never been set
+ if (BARAddr[barnum] == 0)
+ AddMapping(word_value, BARSize[barnum]-1, MMU);
+ else
+ UpdateMapping(BARAddr[barnum], BARSize[barnum]-1,
+ word_value, BARSize[barnum]-1, MMU);
+ BARAddr[barnum] = word_value;
+ }
+
} else {
// This is memory space, bottom four bits are read only
*(uint32_t *)&config.data[offset] = (word_value & ~0xF) |
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index 85f344298..ae8368b71 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -35,16 +35,17 @@
#include "mem/functional_mem/mmap_device.hh"
#include "dev/pcireg.h"
+
class PCIConfigAll;
-/*
- * PCI device configuration device.
+/**
+ * PCI device, base implemnation is only config space.
* Each device is connected to a PCIConfigSpace device
* which returns -1 for everything but the pcidevs that
* register with it. This object registers with the PCIConfig space
* object.
*/
-class PciDev : public MMapDevice
+class PciDev : public MmapDevice
{
private:
uint32_t Bus;
@@ -57,6 +58,7 @@ class PciDev : public MMapDevice
PCIConfigAll *ConfigSpace;
PCIConfig config;
uint32_t BARSize[6];
+ Addr BARAddrs[6];
virtual void WriteConfig(int offset, int size, uint32_t data);
virtual void ReadConfig(int offset, int size, uint8_t *data);