make ide disk work for newmem

SConscript:
    compile ide devices
base/chunk_generator.hh:
    add another parameter to the chuck generator called complete() which
    returns the number of bytes transfered so far. Very useful for
    adding to a pointer.
configs/test/fs.py:
    Add ide disk to fs test configuration
dev/ide_ctrl.cc:
dev/ide_ctrl.hh:
dev/ide_disk.cc:
dev/ide_disk.hh:
dev/io_device.cc:
dev/io_device.hh:
dev/pciconfigall.cc:
dev/pciconfigall.hh:
dev/pcidev.cc:
dev/pcidev.hh:
    update for new memory system
mem/bus.cc:
    support devices that return multiple ranges
    remove old ranges before using new info
mem/packet.hh:
    make senderstate void* per steve's request that we use every
    construct possible in C++
mem/physical.cc:
    have memory stamp the packet with the time.
mem/physical.hh:
    actually set the memory latency variable
python/m5/objects/Device.py:
    Add DmaDevice
python/m5/objects/Ide.py:
    Ide disk no longer has a physmem pointer
python/m5/objects/Pci.py:
    update pci device for newmem
python/m5/objects/PhysicalMemory.py:
    add latency parameter for physical memory
sim/byteswap.hh:
    use fast architecture dependent byteswap calls if they exist

--HG--
extra : convert_revision : e3cf2e8f61064ad302d94bc22010a00c59f3f793
This commit is contained in:
Ali Saidi 2006-04-20 17:14:30 -04:00
parent 9a41591693
commit 6dc3b2fa39
22 changed files with 742 additions and 794 deletions

View file

@ -186,9 +186,12 @@ full_system_sources = Split('''
dev/alpha_console.cc dev/alpha_console.cc
dev/baddev.cc dev/baddev.cc
dev/disk_image.cc dev/disk_image.cc
dev/ide_ctrl.cc
dev/ide_disk.cc
dev/io_device.cc dev/io_device.cc
dev/isa_fake.cc dev/isa_fake.cc
dev/pciconfigall.cc dev/pciconfigall.cc
dev/pcidev.cc
dev/platform.cc dev/platform.cc
dev/simconsole.cc dev/simconsole.cc
dev/simple_disk.cc dev/simple_disk.cc
@ -219,10 +222,7 @@ full_system_sources = Split('''
# dev/etherlink.cc # dev/etherlink.cc
# dev/etherpkt.cc # dev/etherpkt.cc
# dev/ethertap.cc # dev/ethertap.cc
# dev/ide_ctrl.cc
# dev/ide_disk.cc
# dev/ns_gige.cc # dev/ns_gige.cc
# dev/pcidev.cc
# dev/pcifake.cc # dev/pcifake.cc
# dev/pktfifo.cc # dev/pktfifo.cc
# dev/sinic.cc # dev/sinic.cc

View file

@ -62,6 +62,8 @@ class ChunkGenerator
int curSize; int curSize;
/** The number of bytes remaining in the region after the current chunk. */ /** The number of bytes remaining in the region after the current chunk. */
int sizeLeft; int sizeLeft;
/** The start address so we can calculate offset in writing block. */
const Addr startAddr;
/** The maximum chunk size, e.g., the cache block size or page size. */ /** The maximum chunk size, e.g., the cache block size or page size. */
const int chunkSize; const int chunkSize;
@ -73,8 +75,8 @@ class ChunkGenerator
* @param _chunkSize The size/alignment of chunks into which * @param _chunkSize The size/alignment of chunks into which
* the region should be decomposed. * the region should be decomposed.
*/ */
ChunkGenerator(Addr startAddr, int totalSize, int _chunkSize) ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize)
: chunkSize(_chunkSize) : startAddr(_startAddr), chunkSize(_chunkSize)
{ {
// chunkSize must be a power of two // chunkSize must be a power of two
assert(chunkSize == 0 || isPowerOf2(chunkSize)); assert(chunkSize == 0 || isPowerOf2(chunkSize));
@ -107,6 +109,8 @@ class ChunkGenerator
/** Return size in bytes of current chunk. */ /** Return size in bytes of current chunk. */
int size() { return curSize; } int size() { return curSize; }
/** Number of bytes we have already chunked up. */
int complete() { return curAddr - startAddr; }
/** /**
* Are we done? That is, did the last call to next() advance * Are we done? That is, did the last call to next() advance
* past the end of the region? * past the end of the region?

View file

@ -1,9 +1,50 @@
from m5 import *
import os import os
from SysPaths import * from SysPaths import *
# Base for tests is directory containing this file. # Base for tests is directory containing this file.
test_base = os.path.dirname(__file__) test_base = os.path.dirname(__file__)
linux_image = env.get('LINUX_IMAGE', disk('linux-latest.img'))
class IdeControllerPciData(PciConfigData):
VendorID = 0x8086
DeviceID = 0x7111
Command = 0x0
Status = 0x280
Revision = 0x0
ClassCode = 0x01
SubClassCode = 0x01
ProgIF = 0x85
BAR0 = 0x00000001
BAR1 = 0x00000001
BAR2 = 0x00000001
BAR3 = 0x00000001
BAR4 = 0x00000001
BAR5 = 0x00000001
InterruptLine = 0x1f
InterruptPin = 0x01
BAR0Size = '8B'
BAR1Size = '4B'
BAR2Size = '8B'
BAR3Size = '4B'
BAR4Size = '16B'
class LinuxRootDisk(IdeDisk):
raw_image = RawDiskImage(image_file=linux_image, read_only=True)
image = CowDiskImage(child=Parent.raw_image, read_only=False)
class LinuxSwapDisk(IdeDisk):
raw_image = RawDiskImage(image_file = disk('linux-bigswap2.img'),
read_only=True)
image = CowDiskImage(child = Parent.raw_image, read_only=False)
class SpecwebFilesetDisk(IdeDisk):
raw_image = RawDiskImage(image_file = disk('specweb-fileset.img'),
read_only=True)
image = CowDiskImage(child = Parent.raw_image, read_only=False)
class BaseTsunami(Tsunami): class BaseTsunami(Tsunami):
cchip = TsunamiCChip(pio_addr=0x801a0000000) cchip = TsunamiCChip(pio_addr=0x801a0000000)
pchip = TsunamiPChip(pio_addr=0x80180000000) pchip = TsunamiPChip(pio_addr=0x80180000000)
@ -48,17 +89,19 @@ class BaseTsunami(Tsunami):
# configdata=IdeControllerPciData(), # configdata=IdeControllerPciData(),
# pci_func=0, pci_dev=0, pci_bus=0) # pci_func=0, pci_dev=0, pci_bus=0)
#class LinuxTsunami(BaseTsunami): class LinuxTsunami(BaseTsunami):
# disk0 = LinuxRootDisk(delay='0us', driveID='master') disk0 = LinuxRootDisk(driveID='master')
# ide = IdeController(disks=[Parent.disk0], disk1 = SpecwebFilesetDisk(driveID='slave')
# configdata=IdeControllerPciData(), disk2 = LinuxSwapDisk(driveID='master')
# pci_func=0, pci_dev=0, pci_bus=0) ide = IdeController(disks=[Parent.disk0, Parent.disk1, Parent.disk2],
configdata=IdeControllerPciData(),
pci_func=0, pci_dev=0, pci_bus=0)
class LinuxAlphaSystem(LinuxAlphaSystem): class LinuxAlphaSystem(LinuxAlphaSystem):
magicbus = Bus() magicbus = Bus()
physmem = PhysicalMemory(range = AddrRange('128MB')) physmem = PhysicalMemory(range = AddrRange('128MB'))
c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus) c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus)
tsunami = BaseTsunami() tsunami = LinuxTsunami()
c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus) c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus) c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus) c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus)
@ -67,6 +110,8 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus) c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus)
c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus) c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus)
c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus) c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus)
c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus)
c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus)
c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus) c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus)
c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus) c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus)
c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus) c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus)
@ -85,7 +130,7 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus) c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus)
c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus) c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus)
c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus) c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus)
raw_image = RawDiskImage(image_file=disk('linux.img'), raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
read_only=True) read_only=True)
simple_disk = SimpleDisk(disk=Parent.raw_image) simple_disk = SimpleDisk(disk=Parent.raw_image)
intrctrl = IntrControl() intrctrl = IntrControl()

View file

@ -31,7 +31,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "arch/alpha/ev5.hh"
#include "base/trace.hh" #include "base/trace.hh"
#include "cpu/intr_control.hh" #include "cpu/intr_control.hh"
#include "dev/ide_ctrl.hh" #include "dev/ide_ctrl.hh"
@ -39,17 +38,12 @@
#include "dev/pciconfigall.hh" #include "dev/pciconfigall.hh"
#include "dev/pcireg.h" #include "dev/pcireg.h"
#include "dev/platform.hh" #include "dev/platform.hh"
#include "mem/bus/bus.hh" #include "mem/packet.hh"
#include "mem/bus/dma_interface.hh"
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
#include "sim/byteswap.hh"
using namespace std; using namespace std;
using namespace TheISA;
//// ////
// Initialization and destruction // Initialization and destruction
@ -92,22 +86,6 @@ IdeController::IdeController(Params *p)
bm_enabled = false; bm_enabled = false;
memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
pioInterface = NULL;
dmaInterface = NULL;
// create the PIO and DMA interfaces
if (params()->pio_bus) {
pioInterface = newPioInterface(name() + ".pio", params()->hier,
params()->pio_bus, this,
&IdeController::cacheAccess);
pioLatency = params()->pio_latency * params()->pio_bus->clockRate;
}
if (params()->dma_bus) {
dmaInterface = new DMAInterface<Bus>(name() + ".dma",
params()->dma_bus,
params()->dma_bus, 1, true);
}
// setup the disks attached to controller // setup the disks attached to controller
memset(disks, 0, sizeof(disks)); memset(disks, 0, sizeof(disks));
dev[0] = 0; dev[0] = 0;
@ -118,7 +96,7 @@ IdeController::IdeController(Params *p)
for (int i = 0; i < params()->disks.size(); i++) { for (int i = 0; i < params()->disks.size(); i++) {
disks[i] = params()->disks[i]; disks[i] = params()->disks[i];
disks[i]->setController(this, dmaInterface); disks[i]->setController(this);
} }
} }
@ -240,91 +218,158 @@ IdeController::setDmaComplete(IdeDisk *disk)
} }
} }
////
// Bus timing and bus access functions
////
Tick
IdeController::cacheAccess(MemReqPtr &req)
{
// @todo Add more accurate timing to cache access
return curTick + pioLatency;
}
//// ////
// Read and write handling // Read and write handling
//// ////
void void
IdeController::readConfig(int offset, int size, uint8_t *data) IdeController::readConfig(int offset, uint8_t *data)
{ {
int config_offset;
if (offset < PCI_DEVICE_SPECIFIC) { if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::readConfig(offset, size, data); PciDev::readConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START && } else if (offset >= IDE_CTRL_CONF_START &&
(offset + size) <= IDE_CTRL_CONF_END) { (offset + 1) <= IDE_CTRL_CONF_END) {
config_offset = offset - IDE_CTRL_CONF_START; switch (offset) {
case IDE_CTRL_CONF_DEV_TIMING:
switch (size) { *data = config_regs.sidetim;
case sizeof(uint8_t):
*data = config_regs.data[config_offset];
break; break;
case sizeof(uint16_t): case IDE_CTRL_CONF_UDMA_CNTRL:
*(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset]; *data = config_regs.udmactl;
break; break;
case sizeof(uint32_t): case IDE_CTRL_CONF_PRIM_TIMING+1:
*(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset]; *data = htole(config_regs.idetim0) >> 8;
break;
case IDE_CTRL_CONF_SEC_TIMING+1:
*data = htole(config_regs.idetim1) >> 8;
break;
case IDE_CTRL_CONF_IDE_CONFIG:
*data = htole(config_regs.ideconfig) & 0xFF;
break;
case IDE_CTRL_CONF_IDE_CONFIG+1:
*data = htole(config_regs.ideconfig) >> 8;
break; break;
default: default:
panic("Invalid PCI configuration read size!\n"); panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
offset);
} }
DPRINTF(IdeCtrl, "PCI read offset: %#x size: %#x data: %#x\n",
offset, size, *(uint32_t*)data);
} else { } else {
panic("Read of unimplemented PCI config. register: %x\n", offset); panic("Read of unimplemented PCI config. register: %x\n", offset);
} }
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n",
offset, (uint32_t)*data);
} }
void void
IdeController::writeConfig(int offset, int size, const uint8_t *data) IdeController::readConfig(int offset, uint16_t *data)
{ {
int config_offset;
if (offset < PCI_DEVICE_SPECIFIC) { if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, size, data); PciDev::readConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START && } else if (offset >= IDE_CTRL_CONF_START &&
(offset + size) <= IDE_CTRL_CONF_END) { (offset + 2) <= IDE_CTRL_CONF_END) {
config_offset = offset - IDE_CTRL_CONF_START; switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING:
switch(size) { *data = config_regs.idetim0;
case sizeof(uint8_t):
config_regs.data[config_offset] = *data;
break; break;
case sizeof(uint16_t): case IDE_CTRL_CONF_SEC_TIMING:
*(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data; *data = config_regs.idetim1;
break; break;
case sizeof(uint32_t): case IDE_CTRL_CONF_UDMA_TIMING:
*(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data; *data = config_regs.udmatim;
break;
case IDE_CTRL_CONF_IDE_CONFIG:
*data = config_regs.ideconfig;
break; break;
default: default:
panic("Invalid PCI configuration write size!\n"); panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
offset);
} }
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data);
}
void
IdeController::readConfig(int offset, uint32_t *data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::readConfig(offset, data);
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data);
}
void
IdeController::writeConfig(int offset, const uint8_t data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
(offset + 1) <= IDE_CTRL_CONF_END) {
switch (offset) {
case IDE_CTRL_CONF_DEV_TIMING:
config_regs.sidetim = data;
break;
case IDE_CTRL_CONF_UDMA_CNTRL:
config_regs.udmactl = data;
break;
case IDE_CTRL_CONF_IDE_CONFIG:
config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data);
break;
case IDE_CTRL_CONF_IDE_CONFIG+1:
config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8;
break;
default:
panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
offset);
}
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
offset, (uint32_t)data);
}
void
IdeController::writeConfig(int offset, const uint16_t data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
(offset + 2) <= IDE_CTRL_CONF_END) {
switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING:
config_regs.idetim0 = data;
break;
case IDE_CTRL_CONF_SEC_TIMING:
config_regs.idetim1 = data;
break;
case IDE_CTRL_CONF_UDMA_TIMING:
config_regs.udmatim = data;
break;
case IDE_CTRL_CONF_IDE_CONFIG:
config_regs.ideconfig = data;
break;
default:
panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
offset);
}
} else { } else {
panic("Write of unimplemented PCI config. register: %x\n", offset); panic("Write of unimplemented PCI config. register: %x\n", offset);
} }
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data);
DPRINTF(IdeCtrl, "PCI write offset: %#x size: %#x data: %#x\n", /* Trap command register writes and enable IO/BM as appropriate. */
offset, size, data); if (offset == PCI_COMMAND) {
// Catch the writes to specific PCI registers that have side affects
// (like updating the PIO ranges)
switch (offset) {
case PCI_COMMAND:
if (letoh(config.command) & PCI_CMD_IOSE) if (letoh(config.command) & PCI_CMD_IOSE)
io_enabled = true; io_enabled = true;
else else
@ -334,91 +379,111 @@ IdeController::writeConfig(int offset, int size, const uint8_t *data)
bm_enabled = true; bm_enabled = true;
else else
bm_enabled = false; bm_enabled = false;
break; }
}
void
IdeController::writeConfig(int offset, const uint32_t data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, data);
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data);
switch(offset) {
case PCI0_BASE_ADDR0: case PCI0_BASE_ADDR0:
if (BARAddrs[0] != 0) { if (BARAddrs[0] != 0)
pri_cmd_addr = BARAddrs[0]; pri_cmd_addr = BARAddrs[0];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(pri_cmd_addr,
pri_cmd_size));
pri_cmd_addr &= EV5::PAddrUncachedMask;
}
break; break;
case PCI0_BASE_ADDR1: case PCI0_BASE_ADDR1:
if (BARAddrs[1] != 0) { if (BARAddrs[1] != 0)
pri_ctrl_addr = BARAddrs[1]; pri_ctrl_addr = BARAddrs[1];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(pri_ctrl_addr,
pri_ctrl_size));
pri_ctrl_addr &= EV5::PAddrUncachedMask;
}
break; break;
case PCI0_BASE_ADDR2: case PCI0_BASE_ADDR2:
if (BARAddrs[2] != 0) { if (BARAddrs[2] != 0)
sec_cmd_addr = BARAddrs[2]; sec_cmd_addr = BARAddrs[2];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(sec_cmd_addr,
sec_cmd_size));
sec_cmd_addr &= EV5::PAddrUncachedMask;
}
break; break;
case PCI0_BASE_ADDR3: case PCI0_BASE_ADDR3:
if (BARAddrs[3] != 0) { if (BARAddrs[3] != 0)
sec_ctrl_addr = BARAddrs[3]; sec_ctrl_addr = BARAddrs[3];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(sec_ctrl_addr,
sec_ctrl_size));
sec_ctrl_addr &= EV5::PAddrUncachedMask;
}
break; break;
case PCI0_BASE_ADDR4: case PCI0_BASE_ADDR4:
if (BARAddrs[4] != 0) { if (BARAddrs[4] != 0)
bmi_addr = BARAddrs[4]; bmi_addr = BARAddrs[4];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
bmi_addr &= EV5::PAddrUncachedMask;
}
break; break;
} }
} }
Fault Tick
IdeController::read(MemReqPtr &req, uint8_t *data) IdeController::read(Packet &pkt)
{ {
Addr offset; Addr offset;
IdeChannel channel; IdeChannel channel;
IdeRegType reg_type; IdeRegType reg_type;
int disk; int disk;
parseAddr(req->paddr, offset, channel, reg_type); uint8_t *data8 = 0 ;
uint16_t *data16 = 0;
uint32_t *data32 = 0;
if (!io_enabled) switch(pkt.size) {
return NoFault; case sizeof(uint8_t):
if (!pkt.data) {
data8 = new uint8_t;
pkt.data = data8;
} else
data8 = pkt.data;
*data8 = 0;
break;
case sizeof(uint16_t):
if (!pkt.data) {
data16 = new uint16_t;
pkt.data = (uint8_t*)data16;
} else
data16 = (uint16_t*)pkt.data;
*data16 = 0;
break;
case sizeof(uint32_t):
if (!pkt.data) {
data32 = new uint32_t;
pkt.data = (uint8_t*)data32;
} else
data32 = (uint32_t*)pkt.data;
*data32 = 0;
break;
default:
panic("Bad IDE read size: %d\n", pkt.size);
}
parseAddr(pkt.addr, offset, channel, reg_type);
if (!io_enabled) {
pkt.result = Success;
return pioDelay;
}
switch (reg_type) { switch (reg_type) {
case BMI_BLOCK: case BMI_BLOCK:
switch (req->size) { switch (pkt.size) {
case sizeof(uint8_t): case sizeof(uint8_t):
*data = bmi_regs.data[offset]; *data8 = bmi_regs.data[offset];
break; break;
case sizeof(uint16_t): case sizeof(uint16_t):
*(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset]; *data16 = *(uint16_t*)&bmi_regs.data[offset];
break; break;
case sizeof(uint32_t): case sizeof(uint32_t):
*(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset]; *data32 = *(uint32_t*)&bmi_regs.data[offset];
break; break;
default: default:
panic("IDE read of BMI reg invalid size: %#x\n", req->size); panic("IDE read of BMI reg invalid size: %#x\n", pkt.size);
} }
break; break;
@ -431,68 +496,82 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
switch (offset) { switch (offset) {
case DATA_OFFSET: case DATA_OFFSET:
switch (req->size) { switch (pkt.size) {
case sizeof(uint16_t): case sizeof(uint16_t):
disks[disk]->read(offset, reg_type, data); disks[disk]->read(offset, reg_type, (uint8_t*)data16);
break; break;
case sizeof(uint32_t): case sizeof(uint32_t):
disks[disk]->read(offset, reg_type, data); disks[disk]->read(offset, reg_type, (uint8_t*)data16);
disks[disk]->read(offset, reg_type, &data[2]); disks[disk]->read(offset, reg_type, (uint8_t*)(data16 + sizeof(uint16_t)));
break; break;
default: default:
panic("IDE read of data reg invalid size: %#x\n", req->size); panic("IDE read of data reg invalid size: %#x\n", pkt.size);
} }
break; break;
default: default:
if (req->size == sizeof(uint8_t)) { if (pkt.size == sizeof(uint8_t)) {
disks[disk]->read(offset, reg_type, data); disks[disk]->read(offset, reg_type, data8);
} else } else
panic("IDE read of command reg of invalid size: %#x\n", req->size); panic("IDE read of command reg of invalid size: %#x\n", pkt.size);
} }
break; break;
default: default:
panic("IDE controller read of unknown register block type!\n"); panic("IDE controller read of unknown register block type!\n");
} }
if (pkt.size == 1)
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
offset, req->size, *(uint32_t*)data); offset, pkt.size, (uint32_t)*data8);
else if (pkt.size == 2)
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
offset, pkt.size, *data16);
else
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
offset, pkt.size, *data32);
return NoFault; pkt.result = Success;
return pioDelay;
} }
Fault Tick
IdeController::write(MemReqPtr &req, const uint8_t *data) IdeController::write(Packet &pkt)
{ {
Addr offset; Addr offset;
IdeChannel channel; IdeChannel channel;
IdeRegType reg_type; IdeRegType reg_type;
int disk; int disk;
uint8_t oldVal, newVal; uint8_t oldVal, newVal;
uint8_t data8 = *(uint8_t*)pkt.data;
uint32_t data32 = *(uint32_t*)pkt.data;
parseAddr(req->paddr, offset, channel, reg_type);
if (!io_enabled) parseAddr(pkt.addr, offset, channel, reg_type);
return NoFault;
if (!io_enabled) {
pkt.result = Success;
return pioDelay;
}
switch (reg_type) { switch (reg_type) {
case BMI_BLOCK: case BMI_BLOCK:
if (!bm_enabled) if (!bm_enabled) {
return NoFault; pkt.result = Success;
return pioDelay;
}
switch (offset) { switch (offset) {
// Bus master IDE command register // Bus master IDE command register
case BMIC1: case BMIC1:
case BMIC0: case BMIC0:
if (req->size != sizeof(uint8_t)) if (pkt.size != sizeof(uint8_t))
panic("Invalid BMIC write size: %x\n", req->size); panic("Invalid BMIC write size: %x\n", pkt.size);
// select the current disk based on DEV bit // select the current disk based on DEV bit
disk = getDisk(channel); disk = getDisk(channel);
oldVal = bmi_regs.chan[channel].bmic; oldVal = bmi_regs.chan[channel].bmic;
newVal = *data; newVal = data8;
// if a DMA transfer is in progress, R/W control cannot change // if a DMA transfer is in progress, R/W control cannot change
if (oldVal & SSBM) { if (oldVal & SSBM) {
@ -541,11 +620,11 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
// Bus master IDE status register // Bus master IDE status register
case BMIS0: case BMIS0:
case BMIS1: case BMIS1:
if (req->size != sizeof(uint8_t)) if (pkt.size != sizeof(uint8_t))
panic("Invalid BMIS write size: %x\n", req->size); panic("Invalid BMIS write size: %x\n", pkt.size);
oldVal = bmi_regs.chan[channel].bmis; oldVal = bmi_regs.chan[channel].bmis;
newVal = *data; newVal = data8;
// the BMIDEA bit is RO // the BMIDEA bit is RO
newVal |= (oldVal & BMIDEA); newVal |= (oldVal & BMIDEA);
@ -568,30 +647,28 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
case BMIDTP0: case BMIDTP0:
case BMIDTP1: case BMIDTP1:
{ {
if (req->size != sizeof(uint32_t)) if (pkt.size != sizeof(uint32_t))
panic("Invalid BMIDTP write size: %x\n", req->size); panic("Invalid BMIDTP write size: %x\n", pkt.size);
uint32_t host_data = letoh(*(uint32_t*)data); bmi_regs.chan[channel].bmidtp = htole(data32 & ~0x3);
host_data &= ~0x3;
bmi_regs.chan[channel].bmidtp = htole(host_data);
} }
break; break;
default: default:
if (req->size != sizeof(uint8_t) && if (pkt.size != sizeof(uint8_t) &&
req->size != sizeof(uint16_t) && pkt.size != sizeof(uint16_t) &&
req->size != sizeof(uint32_t)) pkt.size != sizeof(uint32_t))
panic("IDE controller write of invalid write size: %x\n", panic("IDE controller write of invalid write size: %x\n",
req->size); pkt.size);
// do a default copy of data into the registers // do a default copy of data into the registers
memcpy(&bmi_regs.data[offset], data, req->size); memcpy(&bmi_regs.data[offset], pkt.data, pkt.size);
} }
break; break;
case COMMAND_BLOCK: case COMMAND_BLOCK:
if (offset == IDE_SELECT_OFFSET) { if (offset == IDE_SELECT_OFFSET) {
uint8_t *devBit = &dev[channel]; uint8_t *devBit = &dev[channel];
*devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0; *devBit = (letoh(data8) & IDE_SELECT_DEV_BIT) ? 1 : 0;
} }
// fall-through ok! // fall-through ok!
case CONTROL_BLOCK: case CONTROL_BLOCK:
@ -602,34 +679,44 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
switch (offset) { switch (offset) {
case DATA_OFFSET: case DATA_OFFSET:
switch (req->size) { switch (pkt.size) {
case sizeof(uint16_t): case sizeof(uint16_t):
disks[disk]->write(offset, reg_type, data); disks[disk]->write(offset, reg_type, pkt.data);
break; break;
case sizeof(uint32_t): case sizeof(uint32_t):
disks[disk]->write(offset, reg_type, data); disks[disk]->write(offset, reg_type, pkt.data);
disks[disk]->write(offset, reg_type, &data[2]); disks[disk]->write(offset, reg_type, pkt.data +
sizeof(uint16_t));
break; break;
default: default:
panic("IDE write of data reg invalid size: %#x\n", req->size); panic("IDE write of data reg invalid size: %#x\n", pkt.size);
} }
break; break;
default: default:
if (req->size == sizeof(uint8_t)) { if (pkt.size == sizeof(uint8_t)) {
disks[disk]->write(offset, reg_type, data); disks[disk]->write(offset, reg_type, pkt.data);
} else } else
panic("IDE write of command reg of invalid size: %#x\n", req->size); panic("IDE write of command reg of invalid size: %#x\n", pkt.size);
} }
break; break;
default: default:
panic("IDE controller write of unknown register block type!\n"); panic("IDE controller write of unknown register block type!\n");
} }
if (pkt.size == 1)
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
offset, req->size, *(uint32_t*)data); offset, pkt.size, (uint32_t)data8);
else if (pkt.size == 2)
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
offset, pkt.size, *(uint16_t*)pkt.data);
else
DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
offset, pkt.size, data32);
return NoFault;
pkt.result = Success;
return pioDelay;
} }
//// ////
@ -698,51 +785,35 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(bm_enabled); UNSERIALIZE_SCALAR(bm_enabled);
UNSERIALIZE_ARRAY(cmd_in_progress, UNSERIALIZE_ARRAY(cmd_in_progress,
sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
if (pioInterface) {
pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size));
pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size));
pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size));
pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size));
pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
}
} }
#ifndef DOXYGEN_SHOULD_SKIP_THIS #ifndef DOXYGEN_SHOULD_SKIP_THIS
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
Param<Addr> addr; SimObjectParam<System *> system;
SimObjectVectorParam<IdeDisk *> disks; SimObjectParam<Platform *> platform;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata; SimObjectParam<PciConfigData *> configdata;
SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus; Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev; Param<uint32_t> pci_dev;
Param<uint32_t> pci_func; Param<uint32_t> pci_func;
SimObjectParam<Bus *> pio_bus;
SimObjectParam<Bus *> dma_bus;
Param<Tick> pio_latency; Param<Tick> pio_latency;
SimObjectParam<HierParams *> hier; SimObjectVectorParam<IdeDisk *> disks;
END_DECLARE_SIM_OBJECT_PARAMS(IdeController) END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(addr, "Device Address"), INIT_PARAM(system, "System pointer"),
INIT_PARAM(disks, "IDE disks attached to this controller"), INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(mmu, "Memory controller"),
INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"), INIT_PARAM(pci_func, "PCI function code"),
INIT_PARAM(pio_bus, ""),
INIT_PARAM(dma_bus, ""),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) INIT_PARAM(disks, "IDE disks attached to this controller")
END_INIT_SIM_OBJECT_PARAMS(IdeController) END_INIT_SIM_OBJECT_PARAMS(IdeController)
@ -750,19 +821,15 @@ CREATE_SIM_OBJECT(IdeController)
{ {
IdeController::Params *params = new IdeController::Params; IdeController::Params *params = new IdeController::Params;
params->name = getInstanceName(); params->name = getInstanceName();
params->mmu = mmu; params->platform = platform;
params->system = system;
params->configSpace = configspace; params->configSpace = configspace;
params->configData = configdata; params->configData = configdata;
params->plat = platform;
params->busNum = pci_bus; params->busNum = pci_bus;
params->deviceNum = pci_dev; params->deviceNum = pci_dev;
params->functionNum = pci_func; params->functionNum = pci_func;
params->pio_delay = pio_latency;
params->disks = disks; params->disks = disks;
params->pio_bus = pio_bus;
params->dma_bus = dma_bus;
params->pio_latency = pio_latency;
params->hier = hier;
return new IdeController(params); return new IdeController(params);
} }

View file

@ -70,6 +70,13 @@
#define IDE_CTRL_CONF_START 0x40 #define IDE_CTRL_CONF_START 0x40
#define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs)) #define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs))
#define IDE_CTRL_CONF_PRIM_TIMING 0x40
#define IDE_CTRL_CONF_SEC_TIMING 0x42
#define IDE_CTRL_CONF_DEV_TIMING 0x44
#define IDE_CTRL_CONF_UDMA_CNTRL 0x48
#define IDE_CTRL_CONF_UDMA_TIMING 0x4A
#define IDE_CTRL_CONF_IDE_CONFIG 0x54
enum IdeRegType { enum IdeRegType {
COMMAND_BLOCK, COMMAND_BLOCK,
@ -77,13 +84,9 @@ enum IdeRegType {
BMI_BLOCK BMI_BLOCK
}; };
class BaseInterface;
class Bus;
class HierParams;
class IdeDisk; class IdeDisk;
class IntrControl; class IntrControl;
class PciConfigAll; class PciConfigAll;
class PhysicalMemory;
class Platform; class Platform;
/** /**
@ -191,10 +194,6 @@ class IdeController : public PciDev
{ {
/** Array of disk objects */ /** Array of disk objects */
std::vector<IdeDisk *> disks; std::vector<IdeDisk *> disks;
Bus *pio_bus;
Bus *dma_bus;
Tick pio_latency;
HierParams *hier;
}; };
const Params *params() const { return (const Params *)_params; } const Params *params() const { return (const Params *)_params; }
@ -202,26 +201,28 @@ class IdeController : public PciDev
IdeController(Params *p); IdeController(Params *p);
~IdeController(); ~IdeController();
virtual void writeConfig(int offset, int size, const uint8_t *data); virtual void writeConfig(int offset, const uint8_t data);
virtual void readConfig(int offset, int size, uint8_t *data); virtual void writeConfig(int offset, const uint16_t data);
virtual void writeConfig(int offset, const uint32_t data);
virtual void readConfig(int offset, uint8_t *data);
virtual void readConfig(int offset, uint16_t *data);
virtual void readConfig(int offset, uint32_t *data);
void setDmaComplete(IdeDisk *disk); void setDmaComplete(IdeDisk *disk);
/** /**
* Read a done field for a given target. * Read a done field for a given target.
* @param req Contains the address of the field to read. * @param pkt Packet describing what is to be read
* @param data Return the field read. * @return The amount of time to complete this request
* @return The fault condition of the access.
*/ */
virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Tick read(Packet &pkt);
/** /**
* Write to the mmapped I/O control registers. * Write a done field for a given target.
* @param req Contains the address to write to. * @param pkt Packet describing what is to be written
* @param data The data to write. * @return The amount of time to complete this request
* @return The fault condition of the access.
*/ */
virtual Fault write(MemReqPtr &req, const uint8_t *data); virtual Tick write(Packet &pkt);
/** /**
* Serialize this object to the given output stream. * Serialize this object to the given output stream.
@ -236,11 +237,5 @@ class IdeController : public PciDev
*/ */
virtual void unserialize(Checkpoint *cp, const std::string &section); 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_ #endif // __IDE_CTRL_HH_

View file

@ -35,6 +35,7 @@
#include <deque> #include <deque>
#include <string> #include <string>
#include "base/chunk_generator.hh"
#include "base/cprintf.hh" // csprintf #include "base/cprintf.hh" // csprintf
#include "base/trace.hh" #include "base/trace.hh"
#include "dev/disk_image.hh" #include "dev/disk_image.hh"
@ -42,11 +43,7 @@
#include "dev/ide_ctrl.hh" #include "dev/ide_ctrl.hh"
#include "dev/tsunami.hh" #include "dev/tsunami.hh"
#include "dev/tsunami_pchip.hh" #include "dev/tsunami_pchip.hh"
#include "mem/functional/physical.hh" #include "mem/packet.hh"
#include "mem/bus/bus.hh"
#include "mem/bus/dma_interface.hh"
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
#include "sim/root.hh" #include "sim/root.hh"
@ -55,11 +52,11 @@
using namespace std; using namespace std;
using namespace TheISA; using namespace TheISA;
IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys, IdeDisk::IdeDisk(const string &name, DiskImage *img,
int id, Tick delay) int id, Tick delay)
: SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay), : SimObject(name), ctrl(NULL), image(img), diskDelay(delay),
dmaTransferEvent(this), dmaReadWaitEvent(this), dmaTransferEvent(this), dmaReadCG(NULL), dmaReadWaitEvent(this),
dmaWriteWaitEvent(this), dmaPrdReadEvent(this), dmaWriteCG(NULL), dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this) dmaReadEvent(this), dmaWriteEvent(this)
{ {
// Reset the device state // Reset the device state
@ -139,7 +136,6 @@ IdeDisk::reset(int id)
memset(&cmdReg, 0, sizeof(CommandReg_t)); memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t)); memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
dmaInterfaceBytes = 0;
curPrdAddr = 0; curPrdAddr = 0;
curSector = 0; curSector = 0;
cmdBytes = 0; cmdBytes = 0;
@ -188,29 +184,6 @@ IdeDisk::pciToDma(Addr pciAddr)
panic("Access to unset controller!\n"); panic("Access to unset controller!\n");
} }
uint32_t
IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
{
uint32_t bytesInPage = 0;
// First calculate how many bytes could be in the page
if (bytesLeft > TheISA::PageBytes)
bytesInPage = TheISA::PageBytes;
else
bytesInPage = bytesLeft;
// Next, see if we have crossed a page boundary, and adjust
Addr upperBound = curAddr + bytesInPage;
Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes;
assert(upperBound >= curAddr && "DMA read wraps around address space!\n");
if (upperBound >= pageBound)
bytesInPage = pageBound - curAddr;
return bytesInPage;
}
//// ////
// Device registers read/write // Device registers read/write
//// ////
@ -339,29 +312,17 @@ IdeDisk::doDmaTransfer()
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n", panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState); dmaState, devState);
// first read the current PRD if (ctrl->dmaPending()) {
if (dmaInterface) { dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
if (dmaInterface->busy()) { return;
// reschedule after waiting period } else
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent,
return; (uint8_t*)&curPrd.entry);
}
dmaInterface->doDMA(Read, curPrdAddr, sizeof(PrdEntry_t), curTick,
&dmaPrdReadEvent);
} else {
dmaPrdReadDone();
}
} }
void void
IdeDisk::dmaPrdReadDone() IdeDisk::dmaPrdReadDone()
{ {
// actually copy the PRD from physical memory
memcpy((void *)&curPrd.entry,
physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)),
sizeof(PrdEntry_t));
DPRINTF(IdeDisk, DPRINTF(IdeDisk,
"PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n", "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()), curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
@ -372,38 +333,49 @@ IdeDisk::dmaPrdReadDone()
curPrdAddr = curPrdAddr + sizeof(PrdEntry_t); curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
if (dmaRead) if (dmaRead)
doDmaRead(); doDmaDataRead();
else else
doDmaWrite(); doDmaDataWrite();
} }
void void
IdeDisk::doDmaRead() IdeDisk::doDmaDataRead()
{ {
/** @todo we need to figure out what the delay actually will be */ /** @todo we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize); Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n", DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
diskDelay, totalDiskDelay); diskDelay, totalDiskDelay);
if (dmaInterface) {
if (dmaInterface->busy()) {
// reschedule after waiting period
dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
}
Addr dmaAddr = pciToDma(curPrd.getBaseAddr()); dmaReadWaitEvent.schedule(curTick + totalDiskDelay);
}
uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
(uint32_t)curPrd.getByteCount());
dmaInterfaceBytes = bytesInPage; void
IdeDisk::doDmaRead()
{
dmaInterface->doDMA(Read, dmaAddr, bytesInPage, if (!dmaReadCG) {
curTick + totalDiskDelay, &dmaReadEvent); // clear out the data buffer
memset(dataBuffer, 0, MAX_DMA_SIZE);
dmaReadCG = new ChunkGenerator(curPrd.getBaseAddr(),
curPrd.getByteCount(), TheISA::PageBytes);
}
if (ctrl->dmaPending()) {
panic("shouldn't be reentant??");
dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else if (!dmaReadCG->done()) {
assert(dmaReadCG->complete() < MAX_DMA_SIZE);
ctrl->dmaRead(pciToDma(dmaReadCG->addr()), dmaReadCG->size(),
&dmaReadWaitEvent, dataBuffer + dmaReadCG->complete());
dmaReadCG->next();
} else { } else {
// schedule dmaReadEvent with sectorDelay (dmaReadDone) assert(dmaReadCG->done());
dmaReadEvent.schedule(curTick + totalDiskDelay); delete dmaReadCG;
dmaReadCG = NULL;
dmaReadDone();
} }
} }
@ -411,63 +383,14 @@ void
IdeDisk::dmaReadDone() IdeDisk::dmaReadDone()
{ {
Addr curAddr = 0, dmaAddr = 0; uint32_t bytesWritten = 0;
uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0;
// continue to use the DMA interface until all pages are read
if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) {
// see if the interface is busy
if (dmaInterface->busy()) {
// reschedule after waiting period
dmaReadEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
}
uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes;
curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes;
dmaAddr = pciToDma(curAddr);
bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
dmaInterfaceBytes += bytesInPage;
dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
curTick, &dmaReadEvent);
return;
}
// set initial address
curAddr = curPrd.getBaseAddr();
// clear out the data buffer
memset(dataBuffer, 0, MAX_DMA_SIZE);
// read the data from memory via DMA into a data buffer
while (bytesWritten < curPrd.getByteCount()) {
if (cmdBytesLeft <= 0)
panic("DMA data is larger than # of sectors specified\n");
dmaAddr = pciToDma(curAddr);
// calculate how many bytes are in the current page
bytesLeft = curPrd.getByteCount() - bytesWritten;
bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
// copy the data from memory into the data buffer
memcpy((void *)(dataBuffer + bytesWritten),
physmem->dma_addr(dmaAddr, bytesInPage),
bytesInPage);
curAddr += bytesInPage;
bytesWritten += bytesInPage;
cmdBytesLeft -= bytesInPage;
}
// write the data to the disk image // write the data to the disk image
for (bytesWritten = 0; for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
bytesWritten < curPrd.getByteCount();
bytesWritten += SectorSize) { bytesWritten += SectorSize) {
cmdBytesLeft -= SectorSize;
writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
} }
@ -482,107 +405,55 @@ IdeDisk::dmaReadDone()
} }
void void
IdeDisk::doDmaWrite() IdeDisk::doDmaDataWrite()
{ {
/** @todo we need to figure out what the delay actually will be */ /** @todo we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize); Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
uint32_t bytesRead = 0;
DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n", DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
diskDelay, totalDiskDelay); diskDelay, totalDiskDelay);
if (dmaInterface) { memset(dataBuffer, 0, MAX_DMA_SIZE);
if (dmaInterface->busy()) { assert(cmdBytesLeft <= MAX_DMA_SIZE);
// reschedule after waiting period while (bytesRead < curPrd.getByteCount()) {
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
return; bytesRead += SectorSize;
} cmdBytesLeft -= SectorSize;
}
Addr dmaAddr = pciToDma(curPrd.getBaseAddr()); dmaWriteWaitEvent.schedule(curTick + totalDiskDelay);
}
uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(), void
(uint32_t)curPrd.getByteCount()); IdeDisk::doDmaWrite()
{
dmaInterfaceBytes = bytesInPage; if (!dmaWriteCG) {
// clear out the data buffer
dmaInterface->doDMA(WriteInvalidate, dmaAddr, dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
bytesInPage, curTick + totalDiskDelay, curPrd.getByteCount(), TheISA::PageBytes);
&dmaWriteEvent); }
if (ctrl->dmaPending()) {
panic("shouldn't be reentant??");
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else if (!dmaWriteCG->done()) {
assert(dmaWriteCG->complete() < MAX_DMA_SIZE);
ctrl->dmaWrite(pciToDma(dmaWriteCG->addr()), dmaWriteCG->size(),
&dmaWriteWaitEvent, dataBuffer + dmaWriteCG->complete());
dmaWriteCG->next();
} else { } else {
// schedule event with disk delay (dmaWriteDone) assert(dmaWriteCG->done());
dmaWriteEvent.schedule(curTick + totalDiskDelay); delete dmaWriteCG;
dmaWriteCG = NULL;
dmaWriteDone();
} }
} }
void void
IdeDisk::dmaWriteDone() IdeDisk::dmaWriteDone()
{ {
Addr curAddr = 0, pageAddr = 0, dmaAddr = 0;
uint32_t bytesRead = 0, bytesInPage = 0;
// continue to use the DMA interface until all pages are read
if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) {
// see if the interface is busy
if (dmaInterface->busy()) {
// reschedule after waiting period
dmaWriteEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
}
uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes;
curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes;
dmaAddr = pciToDma(curAddr);
bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
dmaInterfaceBytes += bytesInPage;
dmaInterface->doDMA(WriteInvalidate, dmaAddr,
bytesInPage, curTick,
&dmaWriteEvent);
return;
}
// setup the initial page and DMA address
curAddr = curPrd.getBaseAddr();
pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
// clear out the data buffer
memset(dataBuffer, 0, MAX_DMA_SIZE);
while (bytesRead < curPrd.getByteCount()) {
// see if we have crossed into a new page
if (pageAddr != TheISA::TruncPage(curAddr)) {
// write the data to memory
memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)),
bytesInPage);
// update the DMA address and page address
pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
bytesInPage = 0;
}
if (cmdBytesLeft <= 0)
panic("DMA requested data is larger than # sectors specified\n");
readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
curAddr += SectorSize;
bytesRead += SectorSize;
bytesInPage += SectorSize;
cmdBytesLeft -= SectorSize;
}
// write the last page worth read to memory
if (bytesInPage != 0) {
memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)),
bytesInPage);
}
// check for the EOT // check for the EOT
if (curPrd.getEOT()) { if (curPrd.getEOT()) {
assert(cmdBytesLeft == 0); assert(cmdBytesLeft == 0);
@ -1138,13 +1009,13 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_SCALAR(curPrd.entry.endOfTable); SERIALIZE_SCALAR(curPrd.entry.endOfTable);
SERIALIZE_SCALAR(curPrdAddr); SERIALIZE_SCALAR(curPrdAddr);
/** @todo need to serialized chunk generator stuff!! */
// Serialize current transfer related information // Serialize current transfer related information
SERIALIZE_SCALAR(cmdBytesLeft); SERIALIZE_SCALAR(cmdBytesLeft);
SERIALIZE_SCALAR(cmdBytes); SERIALIZE_SCALAR(cmdBytes);
SERIALIZE_SCALAR(drqBytesLeft); SERIALIZE_SCALAR(drqBytesLeft);
SERIALIZE_SCALAR(curSector); SERIALIZE_SCALAR(curSector);
SERIALIZE_SCALAR(dmaRead); SERIALIZE_SCALAR(dmaRead);
SERIALIZE_SCALAR(dmaInterfaceBytes);
SERIALIZE_SCALAR(intrPending); SERIALIZE_SCALAR(intrPending);
SERIALIZE_ENUM(devState); SERIALIZE_ENUM(devState);
SERIALIZE_ENUM(dmaState); SERIALIZE_ENUM(dmaState);
@ -1190,13 +1061,13 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(curPrd.entry.endOfTable); UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
UNSERIALIZE_SCALAR(curPrdAddr); UNSERIALIZE_SCALAR(curPrdAddr);
/** @todo need to serialized chunk generator stuff!! */
// Unserialize current transfer related information // Unserialize current transfer related information
UNSERIALIZE_SCALAR(cmdBytes); UNSERIALIZE_SCALAR(cmdBytes);
UNSERIALIZE_SCALAR(cmdBytesLeft); UNSERIALIZE_SCALAR(cmdBytesLeft);
UNSERIALIZE_SCALAR(drqBytesLeft); UNSERIALIZE_SCALAR(drqBytesLeft);
UNSERIALIZE_SCALAR(curSector); UNSERIALIZE_SCALAR(curSector);
UNSERIALIZE_SCALAR(dmaRead); UNSERIALIZE_SCALAR(dmaRead);
UNSERIALIZE_SCALAR(dmaInterfaceBytes);
UNSERIALIZE_SCALAR(intrPending); UNSERIALIZE_SCALAR(intrPending);
UNSERIALIZE_ENUM(devState); UNSERIALIZE_ENUM(devState);
UNSERIALIZE_ENUM(dmaState); UNSERIALIZE_ENUM(dmaState);
@ -1210,7 +1081,6 @@ static const char *DriveID_strings[] = { "master", "slave" };
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk) BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
SimObjectParam<DiskImage *> image; SimObjectParam<DiskImage *> image;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<DriveID> driveID; SimpleEnumParam<DriveID> driveID;
Param<int> delay; Param<int> delay;
@ -1219,7 +1089,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk) BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"), INIT_PARAM(image, "Disk image"),
INIT_PARAM(physmem, "Physical memory"),
INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings), INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1) INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
@ -1228,7 +1097,7 @@ END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
CREATE_SIM_OBJECT(IdeDisk) CREATE_SIM_OBJECT(IdeDisk)
{ {
return new IdeDisk(getInstanceName(), image, physmem, driveID, delay); return new IdeDisk(getInstanceName(), image, driveID, delay);
} }
REGISTER_SIM_OBJECT("IdeDisk", IdeDisk) REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)

View file

@ -42,7 +42,7 @@
#define DMA_BACKOFF_PERIOD 200 #define DMA_BACKOFF_PERIOD 200
#define MAX_DMA_SIZE (65536) // 64K #define MAX_DMA_SIZE (131072) // 128K
#define MAX_MULTSECT (128) #define MAX_MULTSECT (128)
#define PRD_BASE_MASK 0xfffffffe #define PRD_BASE_MASK 0xfffffffe
@ -190,12 +190,8 @@ class IdeDisk : public SimObject
protected: protected:
/** The IDE controller for this disk. */ /** The IDE controller for this disk. */
IdeController *ctrl; IdeController *ctrl;
/** The DMA interface to use for transfers */
DMAInterface<Bus> *dmaInterface;
/** The image that contains the data of this disk. */ /** The image that contains the data of this disk. */
DiskImage *image; DiskImage *image;
/** Pointer to physical memory for DMA transfers */
PhysicalMemory *physmem;
protected: protected:
/** The disk delay in microseconds. */ /** The disk delay in microseconds. */
@ -230,8 +226,6 @@ class IdeDisk : public SimObject
uint32_t curPrdAddr; uint32_t curPrdAddr;
/** PRD entry */ /** PRD entry */
PrdTableEntry curPrd; PrdTableEntry curPrd;
/** Number of bytes transfered by DMA interface for current transfer */
uint32_t dmaInterfaceBytes;
/** Device ID (master=0/slave=1) */ /** Device ID (master=0/slave=1) */
int devID; int devID;
/** Interrupt pending */ /** Interrupt pending */
@ -242,12 +236,10 @@ class IdeDisk : public SimObject
* Create and initialize this Disk. * Create and initialize this Disk.
* @param name The name of this disk. * @param name The name of this disk.
* @param img The disk image of this disk. * @param img The disk image of this disk.
* @param phys Pointer to physical memory
* @param id The disk ID (master=0/slave=1) * @param id The disk ID (master=0/slave=1)
* @param disk_delay The disk delay in milliseconds * @param disk_delay The disk delay in milliseconds
*/ */
IdeDisk(const std::string &name, DiskImage *img, PhysicalMemory *phys, IdeDisk(const std::string &name, DiskImage *img, int id, Tick disk_delay);
int id, Tick disk_delay);
/** /**
* Delete the data buffer. * Delete the data buffer.
@ -263,10 +255,9 @@ class IdeDisk : public SimObject
* Set the controller for this device * Set the controller for this device
* @param c The IDE controller * @param c The IDE controller
*/ */
void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) { void setController(IdeController *c) {
if (ctrl) panic("Cannot change the controller once set!\n"); if (ctrl) panic("Cannot change the controller once set!\n");
ctrl = c; ctrl = c;
dmaInterface = dmaIntr;
} }
// Device register read/write // Device register read/write
@ -289,11 +280,17 @@ class IdeDisk : public SimObject
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>; friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent; EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
void doDmaDataRead();
void doDmaRead(); void doDmaRead();
ChunkGenerator *dmaReadCG;
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>; friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent; EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
void doDmaDataWrite();
void doDmaWrite(); void doDmaWrite();
ChunkGenerator *dmaWriteCG;
friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>; friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent; EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
@ -339,8 +336,6 @@ class IdeDisk : public SimObject
inline Addr pciToDma(Addr pciAddr); inline Addr pciToDma(Addr pciAddr);
uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft);
/** /**
* Serialize this object to the given output stream. * Serialize this object to the given output stream.
* @param os The stream to serialize to. * @param os The stream to serialize to.

View file

@ -105,23 +105,24 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
} }
DmaPort::DmaPort(DmaDevice *dev) DmaPort::DmaPort(DmaDevice *dev, Platform *p)
: device(dev) : device(dev), platform(p), pendingCount(0)
{ } { }
bool bool
DmaPort::recvTiming(Packet &pkt) DmaPort::recvTiming(Packet &pkt)
{ {
completionEvent->schedule(curTick+1); if (pkt.senderState) {
completionEvent = NULL; DmaReqState *state;
state = (DmaReqState*)pkt.senderState;
state->completionEvent->schedule(pkt.time - pkt.req->getTime());
}
return Success; return Success;
} }
DmaDevice::DmaDevice(Params *p) DmaDevice::DmaDevice(Params *p)
: PioDevice(p) : PioDevice(p), dmaPort(NULL)
{ { }
dmaPort = new DmaPort(this);
}
void void
DmaPort::SendEvent::process() DmaPort::SendEvent::process()
@ -140,8 +141,8 @@ DmaPort::recvRetry()
return pkt; return pkt;
} }
void void
DmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size, DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
Event *event, uint8_t *data) uint8_t *data)
{ {
assert(event); assert(event);
@ -161,8 +162,6 @@ DmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
// baseReq.nicReq = true; // baseReq.nicReq = true;
baseReq.setTime(curTick); baseReq.setTime(curTick);
completionEvent = event;
for (ChunkGenerator gen(addr, size, peerBlockSize()); for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) { !gen.done(); gen.next()) {
Packet *pkt = new Packet(basePkt); Packet *pkt = new Packet(basePkt);
@ -175,7 +174,15 @@ DmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
// Increment the data pointer on a write // Increment the data pointer on a write
pkt->data = data ? data + prevSize : NULL ; pkt->data = data ? data + prevSize : NULL ;
prevSize += pkt->size; prevSize += pkt->size;
// Set the last bit of the dma as the final packet for this dma
// and set it's completion event.
if (prevSize == size) {
DmaReqState *state = new DmaReqState(event, true);
pkt->senderState = (void*)state;
}
assert(pendingCount >= 0);
pendingCount++;
sendDma(*pkt); sendDma(*pkt);
} }
} }
@ -194,8 +201,12 @@ DmaPort::sendDma(Packet &pkt)
transmitList.push_back(&packet); transmitList.push_back(&packet);
} else if (state == Atomic) {*/ } else if (state == Atomic) {*/
sendAtomic(pkt); sendAtomic(pkt);
completionEvent->schedule(pkt.time - pkt.req->getTime()); if (pkt.senderState) {
completionEvent = NULL; DmaReqState *state = (DmaReqState*)pkt.senderState;
state->completionEvent->schedule(curTick + (pkt.time - pkt.req->getTime()) +1);
}
pendingCount--;
assert(pendingCount >= 0);
/* } else if (state == Functional) { /* } else if (state == Functional) {
sendFunctional(pkt); sendFunctional(pkt);
// Is this correct??? // Is this correct???

View file

@ -113,13 +113,28 @@ class PioPort : public Port
friend class PioPort::SendEvent; friend class PioPort::SendEvent;
}; };
struct DmaReqState
{
Event *completionEvent;
bool final;
DmaReqState(Event *ce, bool f)
: completionEvent(ce), final(f)
{}
};
class DmaPort : public Port class DmaPort : public Port
{ {
protected: protected:
PioDevice *device; DmaDevice *device;
std::list<Packet*> transmitList; std::list<Packet*> transmitList;
Event *completionEvent;
/** The platform that device/port are in. This is used to select which mode
* we are currently operating in. */
Platform *platform;
/** Number of outstanding packets the dma port has. */
int pendingCount;
virtual bool recvTiming(Packet &pkt); virtual bool recvTiming(Packet &pkt);
virtual Tick recvAtomic(Packet &pkt) virtual Tick recvAtomic(Packet &pkt)
@ -152,13 +167,15 @@ class DmaPort : public Port
friend class DmaPort; friend class DmaPort;
}; };
void dmaAction(Command cmd, DmaPort port, Addr addr, int size,
Event *event, uint8_t *data = NULL);
void sendDma(Packet &pkt); void sendDma(Packet &pkt);
public: public:
DmaPort(DmaDevice *dev); DmaPort(DmaDevice *dev, Platform *p);
void dmaAction(Command cmd, Addr addr, int size, Event *event,
uint8_t *data = NULL);
bool dmaPending() { return pendingCount > 0; }
friend class DmaPort::SendEvent; friend class DmaPort::SendEvent;
@ -286,13 +303,27 @@ class DmaDevice : public PioDevice
DmaDevice(Params *p); DmaDevice(Params *p);
virtual ~DmaDevice(); virtual ~DmaDevice();
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
{ dmaPort->dmaAction(Write, addr, size, event, data) ; }
void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL)
{ dmaPort->dmaAction(Read, addr, size, event, data); }
bool dmaPending() { return dmaPort->dmaPending(); }
virtual Port *getPort(const std::string &if_name) virtual Port *getPort(const std::string &if_name)
{ {
if (if_name == "pio") if (if_name == "pio") {
if (pioPort != NULL)
panic("pio port already connected to.");
pioPort = new PioPort(this, params()->platform);
return pioPort; return pioPort;
else if (if_name == "dma") } else if (if_name == "dma") {
if (dmaPort != NULL)
panic("dma port already connected to.");
dmaPort = new DmaPort(this, params()->platform);
return dmaPort; return dmaPort;
else } else
return NULL; return NULL;
} }

View file

@ -37,7 +37,7 @@
#include "base/trace.hh" #include "base/trace.hh"
#include "dev/pciconfigall.hh" #include "dev/pciconfigall.hh"
//#include "dev/pcidev.hh" #include "dev/pcidev.hh"
#include "dev/pcireg.h" #include "dev/pcireg.h"
#include "dev/platform.hh" #include "dev/platform.hh"
#include "mem/packet.hh" #include "mem/packet.hh"
@ -68,7 +68,7 @@ PciConfigAll::PciConfigAll(Params *p)
void void
PciConfigAll::startup() PciConfigAll::startup()
{ {
/* bitset<256> intLines; bitset<256> intLines;
PciDev *tempDev; PciDev *tempDev;
uint8_t intline; uint8_t intline;
@ -85,7 +85,7 @@ PciConfigAll::startup()
} // devices != NULL } // devices != NULL
} // PCI_FUNC } // PCI_FUNC
} // PCI_DEV } // PCI_DEV
*/
} }
Tick Tick
@ -97,7 +97,7 @@ PciConfigAll::read(Packet &pkt)
Addr daddr = pkt.addr - pioAddr; Addr daddr = pkt.addr - pioAddr;
int device = (daddr >> 11) & 0x1F; int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7; int func = (daddr >> 8) & 0x7;
//int reg = daddr & 0xFF; int reg = daddr & 0xFF;
pkt.time = curTick + pioDelay; pkt.time = curTick + pioDelay;
@ -131,7 +131,7 @@ PciConfigAll::read(Packet &pkt)
if (devices[device][func] == NULL) if (devices[device][func] == NULL)
*data32 = 0xFFFFFFFF; *data32 = 0xFFFFFFFF;
else else
;//devices[device][func]->readConfig(reg, req.size, data32); devices[device][func]->readConfig(reg, data32);
break; break;
case sizeof(uint16_t): case sizeof(uint16_t):
if (!pkt.data) { if (!pkt.data) {
@ -143,7 +143,7 @@ PciConfigAll::read(Packet &pkt)
if (devices[device][func] == NULL) if (devices[device][func] == NULL)
*data16 = 0xFFFF; *data16 = 0xFFFF;
else else
;//devices[device][func]->readConfig(reg, req.size, data16); devices[device][func]->readConfig(reg, data16);
break; break;
case sizeof(uint8_t): case sizeof(uint8_t):
if (!pkt.data) { if (!pkt.data) {
@ -155,7 +155,7 @@ PciConfigAll::read(Packet &pkt)
if (devices[device][func] == NULL) if (devices[device][func] == NULL)
*data8 = 0xFF; *data8 = 0xFF;
else else
;//devices[device][func]->readConfig(reg, req.size, data8); devices[device][func]->readConfig(reg, data8);
break; break;
default: default:
panic("invalid access size(?) for PCI configspace!\n"); panic("invalid access size(?) for PCI configspace!\n");
@ -177,7 +177,7 @@ PciConfigAll::write(Packet &pkt)
int device = (daddr >> 11) & 0x1F; int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7; int func = (daddr >> 8) & 0x7;
// int reg = daddr & 0xFF; int reg = daddr & 0xFF;
if (devices[device][func] == NULL) if (devices[device][func] == NULL)
panic("Attempting to write to config space on non-existant device\n"); panic("Attempting to write to config space on non-existant device\n");
@ -185,8 +185,19 @@ PciConfigAll::write(Packet &pkt)
DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n", DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
pkt.addr, pkt.size, *(uint32_t*)pkt.data); pkt.addr, pkt.size, *(uint32_t*)pkt.data);
// devices[device][func]->writeConfig(reg, req->size, data); switch (pkt.size) {
case sizeof(uint8_t):
devices[device][func]->writeConfig(reg, *pkt.data);
break;
case sizeof(uint16_t):
devices[device][func]->writeConfig(reg, *(uint16_t*)pkt.data);
break;
case sizeof(uint32_t):
devices[device][func]->writeConfig(reg, *(uint32_t*)pkt.data);
break;
default:
panic("invalid pci config write size\n");
}
return pioDelay; return pioDelay;
} }

View file

@ -54,8 +54,6 @@ class PciDev;
class PciConfigAll : public BasicPioDevice class PciConfigAll : public BasicPioDevice
{ {
private: private:
static const Addr size = 0xffffff;
/** /**
* Pointers to all the devices that are registered with this * Pointers to all the devices that are registered with this
* particular config space. * particular config space.

View file

@ -39,20 +39,20 @@
#include "base/misc.hh" #include "base/misc.hh"
#include "base/str.hh" // for to_number #include "base/str.hh" // for to_number
#include "base/trace.hh" #include "base/trace.hh"
#include "dev/pcidev.hh"
#include "dev/pciconfigall.hh" #include "dev/pciconfigall.hh"
#include "mem/bus/bus.hh" #include "dev/pcidev.hh"
#include "mem/functional/memory_control.hh" #include "dev/tsunamireg.h"
#include "mem/packet.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/byteswap.hh"
#include "sim/param.hh" #include "sim/param.hh"
#include "sim/root.hh" #include "sim/root.hh"
#include "dev/tsunamireg.h"
using namespace std; using namespace std;
PciDev::PciDev(Params *p) PciDev::PciDev(Params *p)
: DmaDevice(p->name, p->plat), _params(p), plat(p->plat), : DmaDevice(p), plat(p->platform), configData(p->configData),
configData(p->configData) pioDelay(p->pio_delay)
{ {
// copy the config data from the PciConfigData object // copy the config data from the PciConfigData object
if (configData) { if (configData) {
@ -70,214 +70,180 @@ PciDev::PciDev(Params *p)
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this); p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
} }
Fault
PciDev::read(MemReqPtr &req, uint8_t *data)
{ return NoFault; }
Fault
PciDev::write(MemReqPtr &req, const uint8_t *data)
{ return NoFault; }
Fault
PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::readBar1(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
Fault
PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data)
{ panic("not implemented"); }
void void
PciDev::readConfig(int offset, int size, uint8_t *data) PciDev::readConfig(int offset, uint8_t *data)
{ {
if (offset >= PCI_DEVICE_SPECIFIC) if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n"); panic("Device specific PCI config space not implemented!\n");
switch(size) { *data = config.data[offset];
case sizeof(uint8_t):
*data = config.data[offset];
break;
case sizeof(uint16_t):
*(uint16_t*)data = *(uint16_t*)&config.data[offset];
break;
case sizeof(uint32_t):
*(uint32_t*)data = *(uint32_t*)&config.data[offset];
break;
default:
panic("Invalid PCI configuration read size!\n");
}
DPRINTF(PCIDEV, DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n", "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, size, params()->deviceNum, params()->functionNum, offset, *data);
*(uint32_t*)data);
} }
void void
PciDev::writeConfig(int offset, int size, const uint8_t *data) PciDev::addressRanges(AddrRangeList &range_list)
{
int x = 0;
range_list.clear();
for (x = 0; x < 6; x++)
if (BARAddrs[x] != 0)
range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
}
void
PciDev::readConfig(int offset, uint16_t *data)
{ {
if (offset >= PCI_DEVICE_SPECIFIC) if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n"); panic("Device specific PCI config space not implemented!\n");
uint8_t &data8 = *(uint8_t*)data; *data = *(uint16_t*)&config.data[offset];
uint16_t &data16 = *(uint16_t*)data;
uint32_t &data32 = *(uint32_t*)data;
DPRINTF(PCIDEV, DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n", "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, size, data32); params()->deviceNum, params()->functionNum, offset, *data);
}
switch (size) { void
case sizeof(uint8_t): // 1-byte access PciDev::readConfig(int offset, uint32_t *data)
switch (offset) { {
case PCI0_INTERRUPT_LINE: if (offset >= PCI_DEVICE_SPECIFIC)
config.interruptLine = data8; panic("Device specific PCI config space not implemented!\n");
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data8; *data = *(uint32_t*)&config.data[offset];
case PCI_LATENCY_TIMER:
config.latencyTimer = data8; DPRINTF(PCIDEV,
break; "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
/* Do nothing for these read-only registers */ params()->deviceNum, params()->functionNum, offset, *data);
case PCI0_INTERRUPT_PIN: }
case PCI0_MINIMUM_GRANT:
case PCI0_MAXIMUM_LATENCY:
case PCI_CLASS_CODE: void
case PCI_REVISION_ID: PciDev::writeConfig(int offset, const uint8_t data)
break; {
default: if (offset >= PCI_DEVICE_SPECIFIC)
panic("writing to a read only register"); panic("Device specific PCI config space not implemented!\n");
}
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: 1 data: %#x\n",
params()->deviceNum, params()->functionNum, offset, data);
switch (offset) {
case PCI0_INTERRUPT_LINE:
config.interruptLine = data;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data;
case PCI_LATENCY_TIMER:
config.latencyTimer = data;
break; break;
/* Do nothing for these read-only registers */
case sizeof(uint16_t): // 2-byte access case PCI0_INTERRUPT_PIN:
switch (offset) { case PCI0_MINIMUM_GRANT:
case PCI_COMMAND: case PCI0_MAXIMUM_LATENCY:
config.command = data16; case PCI_CLASS_CODE:
case PCI_STATUS: case PCI_REVISION_ID:
config.status = data16;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data16;
break;
default:
panic("writing to a read only register");
}
break; break;
default:
panic("writing to a read only register");
}
}
case sizeof(uint32_t): // 4-byte access void
switch (offset) { PciDev::writeConfig(int offset, const uint16_t data)
case PCI0_BASE_ADDR0: {
case PCI0_BASE_ADDR1: if (offset >= PCI_DEVICE_SPECIFIC)
case PCI0_BASE_ADDR2: panic("Device specific PCI config space not implemented!\n");
case PCI0_BASE_ADDR3:
case PCI0_BASE_ADDR4:
case PCI0_BASE_ADDR5:
uint32_t barnum, bar_mask; DPRINTF(PCIDEV,
Addr base_addr, base_size, space_base; "write device: %#x function: %#x reg: %#x size: 2 data: %#x\n",
params()->deviceNum, params()->functionNum, offset, data);
barnum = BAR_NUMBER(offset); switch (offset) {
case PCI_COMMAND:
config.command = data;
case PCI_STATUS:
config.status = data;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data;
break;
default:
panic("writing to a read only register");
}
}
if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
bar_mask = BAR_IO_MASK;
space_base = TSUNAMI_PCI0_IO;
} else {
bar_mask = BAR_MEM_MASK;
space_base = TSUNAMI_PCI0_MEMORY;
}
// Writing 0xffffffff to a BAR tells the card to set the void
// value of the bar to size of memory it needs PciDev::writeConfig(int offset, const uint32_t data)
if (letoh(data32) == 0xffffffff) { {
// This is I/O Space, bottom two bits are read only if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
config.baseAddr[barnum] = letoh( DPRINTF(PCIDEV,
(~(BARSize[barnum] - 1) & ~bar_mask) | "write device: %#x function: %#x reg: %#x size: 4 data: %#x\n",
(letoh(config.baseAddr[barnum]) & bar_mask)); params()->deviceNum, params()->functionNum, offset, data);
} else {
MemoryController *mmu = params()->mmu;
config.baseAddr[barnum] = letoh( switch (offset) {
(letoh(data32) & ~bar_mask) | case PCI0_BASE_ADDR0:
case PCI0_BASE_ADDR1:
case PCI0_BASE_ADDR2:
case PCI0_BASE_ADDR3:
case PCI0_BASE_ADDR4:
case PCI0_BASE_ADDR5:
uint32_t barnum, bar_mask;
Addr base_addr, base_size, space_base;
barnum = BAR_NUMBER(offset);
if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
bar_mask = BAR_IO_MASK;
space_base = TSUNAMI_PCI0_IO;
} else {
bar_mask = BAR_MEM_MASK;
space_base = TSUNAMI_PCI0_MEMORY;
}
// Writing 0xffffffff to a BAR tells the card to set the
// value of the bar to size of memory it needs
if (letoh(data) == 0xffffffff) {
// This is I/O Space, bottom two bits are read only
config.baseAddr[barnum] = letoh(
(~(BARSize[barnum] - 1) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask)); (letoh(config.baseAddr[barnum]) & bar_mask));
} else {
config.baseAddr[barnum] = letoh(
(letoh(data) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
if (letoh(config.baseAddr[barnum]) & ~bar_mask) { if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
base_addr = (letoh(data32) & ~bar_mask) + space_base; base_addr = (letoh(data) & ~bar_mask) + space_base;
base_size = BARSize[barnum]; base_size = BARSize[barnum];
BARAddrs[barnum] = base_addr;
// It's never been set pioPort->sendStatusChange(Port::RangeChange);
if (BARAddrs[barnum] == 0)
mmu->add_child((FunctionalMemory *)this,
RangeSize(base_addr, base_size));
else
mmu->update_child((FunctionalMemory *)this,
RangeSize(BARAddrs[barnum], base_size),
RangeSize(base_addr, base_size));
BARAddrs[barnum] = base_addr;
}
} }
break;
case PCI0_ROM_BASE_ADDR:
if (letoh(data32) == 0xfffffffe)
config.expansionROM = htole((uint32_t)0xffffffff);
else
config.expansionROM = data32;
break;
case PCI_COMMAND:
// This could also clear some of the error bits in the Status
// register. However they should never get set, so lets ignore
// it for now
config.command = data16;
break;
default:
DPRINTF(PCIDEV, "Writing to a read only register");
} }
break; break;
case PCI0_ROM_BASE_ADDR:
if (letoh(data) == 0xfffffffe)
config.expansionROM = htole((uint32_t)0xffffffff);
else
config.expansionROM = data;
break;
case PCI_COMMAND:
// This could also clear some of the error bits in the Status
// register. However they should never get set, so lets ignore
// it for now
config.command = data;
break;
default: default:
panic("invalid access size"); DPRINTF(PCIDEV, "Writing to a read only register");
} }
} }
@ -296,12 +262,6 @@ PciDev::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
UNSERIALIZE_ARRAY(config.data, UNSERIALIZE_ARRAY(config.data,
sizeof(config.data) / sizeof(config.data[0])); sizeof(config.data) / sizeof(config.data[0]));
// Add the MMU mappings for the BARs
for (int i=0; i < 6; i++) {
if (BARAddrs[i] != 0)
params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i]));
}
} }
#ifndef DOXYGEN_SHOULD_SKIP_THIS #ifndef DOXYGEN_SHOULD_SKIP_THIS

View file

@ -44,7 +44,6 @@
#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); #define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
class PciConfigAll; class PciConfigAll;
class MemoryController;
/** /**
@ -85,12 +84,8 @@ class PciConfigData : public SimObject
class PciDev : public DmaDevice class PciDev : public DmaDevice
{ {
public: public:
struct Params struct Params : public ::PioDevice::Params
{ {
std::string name;
Platform *plat;
MemoryController *mmu;
/** /**
* A pointer to the configspace all object that calls us when * A pointer to the configspace all object that calls us when
* a read comes to this particular device/function. * a read comes to this particular device/function.
@ -111,13 +106,13 @@ class PciDev : public DmaDevice
/** The function number */ /** The function number */
uint32_t functionNum; uint32_t functionNum;
/** The latency for pio accesses. */
Tick pio_delay;
}; };
protected:
Params *_params;
public: public:
const Params *params() const { return _params; } const Params *params() const { return (const Params *)_params; }
protected: protected:
/** The current config space. Unlike the PciConfigData this is /** The current config space. Unlike the PciConfigData this is
@ -164,6 +159,7 @@ class PciDev : public DmaDevice
protected: protected:
Platform *plat; Platform *plat;
PciConfigData *configData; PciConfigData *configData;
Tick pioDelay;
public: public:
Addr pciToDma(Addr pciAddr) const Addr pciToDma(Addr pciAddr) const
@ -181,7 +177,11 @@ class PciDev : public DmaDevice
interruptLine() interruptLine()
{ return configData->config.interruptLine; } { return configData->config.interruptLine; }
public: /** return the address ranges that this device responds to.
* @params range_list range list to populate with ranges
*/
void addressRanges(AddrRangeList &range_list);
/** /**
* Constructor for PCI Dev. This function copies data from the * Constructor for PCI Dev. This function copies data from the
* config file object PCIConfigData and registers the device with * config file object PCIConfigData and registers the device with
@ -189,39 +189,6 @@ class PciDev : public DmaDevice
*/ */
PciDev(Params *params); PciDev(Params *params);
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 * 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 * overridden by the device but at some point it will eventually call this
@ -230,7 +197,9 @@ class PciDev : public DmaDevice
* @param size the size of the write * @param size the size of the write
* @param data the data to write * @param data the data to write
*/ */
virtual void writeConfig(int offset, int size, const uint8_t* data); virtual void writeConfig(int offset, const uint8_t data);
virtual void writeConfig(int offset, const uint16_t data);
virtual void writeConfig(int offset, const uint32_t data);
/** /**
@ -241,7 +210,9 @@ class PciDev : public DmaDevice
* @param size the size of the read * @param size the size of the read
* @param data pointer to the location where the read value should be stored * @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, uint8_t *data);
virtual void readConfig(int offset, uint16_t *data);
virtual void readConfig(int offset, uint32_t *data);
/** /**
* Serialize this object to the given output stream. * Serialize this object to the given output stream.
@ -256,43 +227,4 @@ class PciDev : public DmaDevice
*/ */
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };
inline Fault
PciDev::readBar(MemReqPtr &req, uint8_t *data)
{
using namespace TheISA;
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 genMachineCheckFault();
}
inline Fault
PciDev::writeBar(MemReqPtr &req, const uint8_t *data)
{
using namespace TheISA;
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 genMachineCheckFault();
}
#endif // __DEV_PCIDEV_HH__ #endif // __DEV_PCIDEV_HH__

View file

@ -97,21 +97,30 @@ Bus::recvStatusChange(Port::Status status, int id)
Port *port = interfaces[id]; Port *port = interfaces[id];
AddrRangeList ranges; AddrRangeList ranges;
AddrRangeList snoops; AddrRangeList snoops;
AddrRangeIter iter;
std::vector<DevMap>::iterator portIter;
// Clean out any previously existent ids
for (portIter = portList.begin(); portIter != portList.end(); ) {
if (portIter->portId == id)
portIter = portList.erase(portIter);
else
portIter++;
}
port->getPeerAddressRanges(ranges, snoops); port->getPeerAddressRanges(ranges, snoops);
// not dealing with snooping yet either // not dealing with snooping yet either
assert(snoops.size() == 0); assert(snoops.size() == 0);
// or multiple ranges for(iter = ranges.begin(); iter != ranges.end(); iter++) {
assert(ranges.size() == 1); DevMap dm;
dm.portId = id;
dm.range = *iter;
DevMap dm; DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
dm.portId = id; dm.range.end, id);
dm.range = ranges.front(); portList.push_back(dm);
}
DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
dm.range.end, id);
portList.push_back(dm);
DPRINTF(MMU, "port list has %d entries\n", portList.size()); DPRINTF(MMU, "port list has %d entries\n", portList.size());
} }

View file

@ -92,7 +92,7 @@ struct Packet
// assert(dynamic_cast<Foo>) etc. // assert(dynamic_cast<Foo>) etc.
/** A virtual base opaque structure used to hold the senders state. */ /** A virtual base opaque structure used to hold the senders state. */
SenderState *senderState; // virtual base opaque, void *senderState; // virtual base opaque,
// assert(dynamic_cast<Foo>) etc. // assert(dynamic_cast<Foo>) etc.
/** A pointer to the data being transfered. It can be differnt sizes /** A pointer to the data being transfered. It can be differnt sizes

View file

@ -69,8 +69,8 @@ PhysicalMemory::MemResponseEvent::description()
return "Physical Memory Timing Access respnse event"; return "Physical Memory Timing Access respnse event";
} }
PhysicalMemory::PhysicalMemory(const string &n) PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
: MemObject(n), base_addr(0), pmem_addr(NULL), port(NULL) : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
{ {
// Hardcoded to 128 MB for now. // Hardcoded to 128 MB for now.
pmem_size = 1 << 27; pmem_size = 1 << 27;
@ -137,6 +137,7 @@ Tick
PhysicalMemory::doAtomicAccess(Packet &pkt) PhysicalMemory::doAtomicAccess(Packet &pkt)
{ {
doFunctionalAccess(pkt); doFunctionalAccess(pkt);
pkt.time = curTick + lat;
return curTick + lat; return curTick + lat;
} }
@ -344,20 +345,22 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
Param<string> file; Param<string> file;
Param<Range<Addr> > range; Param<Range<Addr> > range;
Param<Tick> latency;
END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory) END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
INIT_PARAM_DFLT(file, "memory mapped file", ""), INIT_PARAM_DFLT(file, "memory mapped file", ""),
INIT_PARAM(range, "Device Address Range") INIT_PARAM(range, "Device Address Range"),
INIT_PARAM(latency, "Memory access latency")
END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory) END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
CREATE_SIM_OBJECT(PhysicalMemory) CREATE_SIM_OBJECT(PhysicalMemory)
{ {
return new PhysicalMemory(getInstanceName()); return new PhysicalMemory(getInstanceName(), latency);
} }
REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory) REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)

View file

@ -71,7 +71,6 @@ class PhysicalMemory : public MemObject
int numPorts; int numPorts;
int lat;
struct MemResponseEvent : public Event struct MemResponseEvent : public Event
{ {
@ -94,13 +93,14 @@ class PhysicalMemory : public MemObject
uint8_t *pmem_addr; uint8_t *pmem_addr;
MemoryPort *port; MemoryPort *port;
int page_ptr; int page_ptr;
Tick lat;
public: public:
Addr new_page(); Addr new_page();
uint64_t size() { return pmem_size; } uint64_t size() { return pmem_size; }
public: public:
PhysicalMemory(const std::string &n); PhysicalMemory(const std::string &n, Tick latency);
virtual ~PhysicalMemory(); virtual ~PhysicalMemory();
public: public:

View file

@ -12,3 +12,7 @@ class BasicPioDevice(PioDevice):
abstract = True abstract = True
pio_addr = Param.Addr("Device Address") pio_addr = Param.Addr("Device Address")
pio_latency = Param.Tick(1, "Programmed IO latency in simticks") pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
class DmaDevice(PioDevice):
type = 'DmaDevice'
abstract = True

View file

@ -8,7 +8,6 @@ class IdeDisk(SimObject):
delay = Param.Latency('1us', "Fixed disk delay in microseconds") delay = Param.Latency('1us', "Fixed disk delay in microseconds")
driveID = Param.IdeID('master', "Drive ID") driveID = Param.IdeID('master', "Drive ID")
image = Param.DiskImage("Disk image") image = Param.DiskImage("Disk image")
physmem = Param.PhysicalMemory(Parent.any, "Physical memory")
class IdeController(PciDevice): class IdeController(PciDevice):
type = 'IdeController' type = 'IdeController'

View file

@ -1,6 +1,5 @@
from m5 import * from m5 import *
from Device import BasicPioDevice from Device import BasicPioDevice, DmaDevice
#, DmaDevice
class PciConfigData(SimObject): class PciConfigData(SimObject):
type = 'PciConfigData' type = 'PciConfigData'
@ -42,15 +41,15 @@ class PciConfigData(SimObject):
class PciConfigAll(BasicPioDevice): class PciConfigAll(BasicPioDevice):
type = 'PciConfigAll' type = 'PciConfigAll'
#class PciDevice(DmaDevice): class PciDevice(DmaDevice):
# type = 'PciDevice' type = 'PciDevice'
# abstract = True abstract = True
# addr = 0xffffffffL pci_bus = Param.Int("PCI bus")
# pci_bus = Param.Int("PCI bus") pci_dev = Param.Int("PCI device number")
# pci_dev = Param.Int("PCI device number") pci_func = Param.Int("PCI function code")
# pci_func = Param.Int("PCI function code") pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
# configdata = Param.PciConfigData(Parent.any, "PCI Config data") configdata = Param.PciConfigData(Parent.any, "PCI Config data")
# configspace = Param.PciConfigAll(Parent.any, "PCI Configspace") configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
#
#class PciFake(PciDevice): class PciFake(PciDevice):
# type = 'PciFake' type = 'PciFake'

View file

@ -1,7 +1,8 @@
from m5 import * from m5 import *
from Memory import Memory from MemObject import *
class PhysicalMemory(Memory): class PhysicalMemory(MemObject):
type = 'PhysicalMemory' type = 'PhysicalMemory'
range = Param.AddrRange("Device Address") range = Param.AddrRange("Device Address")
file = Param.String('', "memory mapped file") file = Param.String('', "memory mapped file")
latency = Param.Latency('10ns', "latency of an access")

View file

@ -38,6 +38,10 @@
// This lets us figure out what the byte order of the host system is // This lets us figure out what the byte order of the host system is
#if defined(linux) #if defined(linux)
#include <endian.h> #include <endian.h>
// If this is a linux system, lets used the optimized definitions if they exist.
// If one doesn't exist, we pretty much get what is listed below, so it all
// works out
#include <byteswap.h>
#else #else
#include <machine/endian.h> #include <machine/endian.h>
#endif #endif
@ -47,6 +51,9 @@
static inline uint64_t static inline uint64_t
swap_byte64(uint64_t x) swap_byte64(uint64_t x)
{ {
#if defined(linux)
return bswap_64(x);
#else
return (uint64_t)((((uint64_t)(x) & 0xff) << 56) | return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
((uint64_t)(x) & 0xff00ULL) << 40 | ((uint64_t)(x) & 0xff00ULL) << 40 |
((uint64_t)(x) & 0xff0000ULL) << 24 | ((uint64_t)(x) & 0xff0000ULL) << 24 |
@ -55,22 +62,30 @@ swap_byte64(uint64_t x)
((uint64_t)(x) & 0xff0000000000ULL) >> 24 | ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
((uint64_t)(x) & 0xff000000000000ULL) >> 40 | ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ; ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
} }
static inline uint32_t static inline uint32_t
swap_byte32(uint32_t x) swap_byte32(uint32_t x)
{ {
#if defined(linux)
return bswap_32(x);
#else
return (uint32_t)(((uint32_t)(x) & 0xff) << 24 | return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 | ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
((uint32_t)(x) & 0xff000000) >> 24); ((uint32_t)(x) & 0xff000000) >> 24);
#endif
} }
static inline uint16_t static inline uint16_t
swap_byte16(uint16_t x) swap_byte16(uint16_t x)
{ {
#if defined(linux)
return bswap_16(x);
#else
return (uint16_t)(((uint16_t)(x) & 0xff) << 8 | return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
((uint16_t)(x) & 0xff00) >> 8); ((uint16_t)(x) & 0xff00) >> 8);
#endif
} }
//This lets the compiler figure out how to call the swap_byte functions above //This lets the compiler figure out how to call the swap_byte functions above