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/baddev.cc
dev/disk_image.cc
dev/ide_ctrl.cc
dev/ide_disk.cc
dev/io_device.cc
dev/isa_fake.cc
dev/pciconfigall.cc
dev/pcidev.cc
dev/platform.cc
dev/simconsole.cc
dev/simple_disk.cc
@ -219,10 +222,7 @@ full_system_sources = Split('''
# dev/etherlink.cc
# dev/etherpkt.cc
# dev/ethertap.cc
# dev/ide_ctrl.cc
# dev/ide_disk.cc
# dev/ns_gige.cc
# dev/pcidev.cc
# dev/pcifake.cc
# dev/pktfifo.cc
# dev/sinic.cc

View file

@ -62,6 +62,8 @@ class ChunkGenerator
int curSize;
/** The number of bytes remaining in the region after the current chunk. */
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. */
const int chunkSize;
@ -73,8 +75,8 @@ class ChunkGenerator
* @param _chunkSize The size/alignment of chunks into which
* the region should be decomposed.
*/
ChunkGenerator(Addr startAddr, int totalSize, int _chunkSize)
: chunkSize(_chunkSize)
ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize)
: startAddr(_startAddr), chunkSize(_chunkSize)
{
// chunkSize must be a power of two
assert(chunkSize == 0 || isPowerOf2(chunkSize));
@ -107,6 +109,8 @@ class ChunkGenerator
/** Return size in bytes of current chunk. */
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
* past the end of the region?

View file

@ -1,9 +1,50 @@
from m5 import *
import os
from SysPaths import *
# Base for tests is directory containing this 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):
cchip = TsunamiCChip(pio_addr=0x801a0000000)
pchip = TsunamiPChip(pio_addr=0x80180000000)
@ -48,17 +89,19 @@ class BaseTsunami(Tsunami):
# configdata=IdeControllerPciData(),
# pci_func=0, pci_dev=0, pci_bus=0)
#class LinuxTsunami(BaseTsunami):
# disk0 = LinuxRootDisk(delay='0us', driveID='master')
# ide = IdeController(disks=[Parent.disk0],
# configdata=IdeControllerPciData(),
# pci_func=0, pci_dev=0, pci_bus=0)
class LinuxTsunami(BaseTsunami):
disk0 = LinuxRootDisk(driveID='master')
disk1 = SpecwebFilesetDisk(driveID='slave')
disk2 = LinuxSwapDisk(driveID='master')
ide = IdeController(disks=[Parent.disk0, Parent.disk1, Parent.disk2],
configdata=IdeControllerPciData(),
pci_func=0, pci_dev=0, pci_bus=0)
class LinuxAlphaSystem(LinuxAlphaSystem):
magicbus = Bus()
physmem = PhysicalMemory(range = AddrRange('128MB'))
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)
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)
@ -67,6 +110,8 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
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)
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)
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)
@ -85,7 +130,7 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
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)
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)
simple_disk = SimpleDisk(disk=Parent.raw_image)
intrctrl = IntrControl()

View file

@ -31,7 +31,6 @@
#include <string>
#include <vector>
#include "arch/alpha/ev5.hh"
#include "base/trace.hh"
#include "cpu/intr_control.hh"
#include "dev/ide_ctrl.hh"
@ -39,17 +38,12 @@
#include "dev/pciconfigall.hh"
#include "dev/pcireg.h"
#include "dev/platform.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 "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
#include "sim/byteswap.hh"
using namespace std;
using namespace TheISA;
////
// Initialization and destruction
@ -92,22 +86,6 @@ IdeController::IdeController(Params *p)
bm_enabled = false;
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
memset(disks, 0, sizeof(disks));
dev[0] = 0;
@ -118,7 +96,7 @@ IdeController::IdeController(Params *p)
for (int i = 0; i < params()->disks.size(); 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
////
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) {
PciDev::readConfig(offset, size, data);
PciDev::readConfig(offset, data);
} 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 (size) {
case sizeof(uint8_t):
*data = config_regs.data[config_offset];
switch (offset) {
case IDE_CTRL_CONF_DEV_TIMING:
*data = config_regs.sidetim;
break;
case sizeof(uint16_t):
*(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset];
case IDE_CTRL_CONF_UDMA_CNTRL:
*data = config_regs.udmactl;
break;
case sizeof(uint32_t):
*(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset];
case IDE_CTRL_CONF_PRIM_TIMING+1:
*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;
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 {
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
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) {
PciDev::writeConfig(offset, size, data);
PciDev::readConfig(offset, data);
} 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(size) {
case sizeof(uint8_t):
config_regs.data[config_offset] = *data;
switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING:
*data = config_regs.idetim0;
break;
case sizeof(uint16_t):
*(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data;
case IDE_CTRL_CONF_SEC_TIMING:
*data = config_regs.idetim1;
break;
case sizeof(uint32_t):
*(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data;
case IDE_CTRL_CONF_UDMA_TIMING:
*data = config_regs.udmatim;
break;
case IDE_CTRL_CONF_IDE_CONFIG:
*data = config_regs.ideconfig;
break;
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 {
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",
offset, size, data);
// Catch the writes to specific PCI registers that have side affects
// (like updating the PIO ranges)
switch (offset) {
case PCI_COMMAND:
/* Trap command register writes and enable IO/BM as appropriate. */
if (offset == PCI_COMMAND) {
if (letoh(config.command) & PCI_CMD_IOSE)
io_enabled = true;
else
@ -334,91 +379,111 @@ IdeController::writeConfig(int offset, int size, const uint8_t *data)
bm_enabled = true;
else
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:
if (BARAddrs[0] != 0) {
if (BARAddrs[0] != 0)
pri_cmd_addr = BARAddrs[0];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(pri_cmd_addr,
pri_cmd_size));
pri_cmd_addr &= EV5::PAddrUncachedMask;
}
break;
case PCI0_BASE_ADDR1:
if (BARAddrs[1] != 0) {
if (BARAddrs[1] != 0)
pri_ctrl_addr = BARAddrs[1];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(pri_ctrl_addr,
pri_ctrl_size));
pri_ctrl_addr &= EV5::PAddrUncachedMask;
}
break;
case PCI0_BASE_ADDR2:
if (BARAddrs[2] != 0) {
if (BARAddrs[2] != 0)
sec_cmd_addr = BARAddrs[2];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(sec_cmd_addr,
sec_cmd_size));
sec_cmd_addr &= EV5::PAddrUncachedMask;
}
break;
case PCI0_BASE_ADDR3:
if (BARAddrs[3] != 0) {
if (BARAddrs[3] != 0)
sec_ctrl_addr = BARAddrs[3];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(sec_ctrl_addr,
sec_ctrl_size));
sec_ctrl_addr &= EV5::PAddrUncachedMask;
}
break;
case PCI0_BASE_ADDR4:
if (BARAddrs[4] != 0) {
if (BARAddrs[4] != 0)
bmi_addr = BARAddrs[4];
if (pioInterface)
pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
bmi_addr &= EV5::PAddrUncachedMask;
}
break;
}
}
Fault
IdeController::read(MemReqPtr &req, uint8_t *data)
Tick
IdeController::read(Packet &pkt)
{
Addr offset;
IdeChannel channel;
IdeRegType reg_type;
int disk;
parseAddr(req->paddr, offset, channel, reg_type);
uint8_t *data8 = 0 ;
uint16_t *data16 = 0;
uint32_t *data32 = 0;
if (!io_enabled)
return NoFault;
switch(pkt.size) {
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) {
case BMI_BLOCK:
switch (req->size) {
switch (pkt.size) {
case sizeof(uint8_t):
*data = bmi_regs.data[offset];
*data8 = bmi_regs.data[offset];
break;
case sizeof(uint16_t):
*(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset];
*data16 = *(uint16_t*)&bmi_regs.data[offset];
break;
case sizeof(uint32_t):
*(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset];
*data32 = *(uint32_t*)&bmi_regs.data[offset];
break;
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;
@ -431,68 +496,82 @@ IdeController::read(MemReqPtr &req, uint8_t *data)
switch (offset) {
case DATA_OFFSET:
switch (req->size) {
switch (pkt.size) {
case sizeof(uint16_t):
disks[disk]->read(offset, reg_type, data);
disks[disk]->read(offset, reg_type, (uint8_t*)data16);
break;
case sizeof(uint32_t):
disks[disk]->read(offset, reg_type, data);
disks[disk]->read(offset, reg_type, &data[2]);
disks[disk]->read(offset, reg_type, (uint8_t*)data16);
disks[disk]->read(offset, reg_type, (uint8_t*)(data16 + sizeof(uint16_t)));
break;
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;
default:
if (req->size == sizeof(uint8_t)) {
disks[disk]->read(offset, reg_type, data);
if (pkt.size == sizeof(uint8_t)) {
disks[disk]->read(offset, reg_type, data8);
} 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;
default:
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",
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
IdeController::write(MemReqPtr &req, const uint8_t *data)
Tick
IdeController::write(Packet &pkt)
{
Addr offset;
IdeChannel channel;
IdeRegType reg_type;
int disk;
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)
return NoFault;
parseAddr(pkt.addr, offset, channel, reg_type);
if (!io_enabled) {
pkt.result = Success;
return pioDelay;
}
switch (reg_type) {
case BMI_BLOCK:
if (!bm_enabled)
return NoFault;
if (!bm_enabled) {
pkt.result = Success;
return pioDelay;
}
switch (offset) {
// Bus master IDE command register
case BMIC1:
case BMIC0:
if (req->size != sizeof(uint8_t))
panic("Invalid BMIC write size: %x\n", req->size);
if (pkt.size != sizeof(uint8_t))
panic("Invalid BMIC write size: %x\n", pkt.size);
// select the current disk based on DEV bit
disk = getDisk(channel);
oldVal = bmi_regs.chan[channel].bmic;
newVal = *data;
newVal = data8;
// if a DMA transfer is in progress, R/W control cannot change
if (oldVal & SSBM) {
@ -541,11 +620,11 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
// Bus master IDE status register
case BMIS0:
case BMIS1:
if (req->size != sizeof(uint8_t))
panic("Invalid BMIS write size: %x\n", req->size);
if (pkt.size != sizeof(uint8_t))
panic("Invalid BMIS write size: %x\n", pkt.size);
oldVal = bmi_regs.chan[channel].bmis;
newVal = *data;
newVal = data8;
// the BMIDEA bit is RO
newVal |= (oldVal & BMIDEA);
@ -568,30 +647,28 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
case BMIDTP0:
case BMIDTP1:
{
if (req->size != sizeof(uint32_t))
panic("Invalid BMIDTP write size: %x\n", req->size);
if (pkt.size != sizeof(uint32_t))
panic("Invalid BMIDTP write size: %x\n", pkt.size);
uint32_t host_data = letoh(*(uint32_t*)data);
host_data &= ~0x3;
bmi_regs.chan[channel].bmidtp = htole(host_data);
bmi_regs.chan[channel].bmidtp = htole(data32 & ~0x3);
}
break;
default:
if (req->size != sizeof(uint8_t) &&
req->size != sizeof(uint16_t) &&
req->size != sizeof(uint32_t))
if (pkt.size != sizeof(uint8_t) &&
pkt.size != sizeof(uint16_t) &&
pkt.size != sizeof(uint32_t))
panic("IDE controller write of invalid write size: %x\n",
req->size);
pkt.size);
// 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;
case COMMAND_BLOCK:
if (offset == IDE_SELECT_OFFSET) {
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!
case CONTROL_BLOCK:
@ -602,34 +679,44 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
switch (offset) {
case DATA_OFFSET:
switch (req->size) {
switch (pkt.size) {
case sizeof(uint16_t):
disks[disk]->write(offset, reg_type, data);
disks[disk]->write(offset, reg_type, pkt.data);
break;
case sizeof(uint32_t):
disks[disk]->write(offset, reg_type, data);
disks[disk]->write(offset, reg_type, &data[2]);
disks[disk]->write(offset, reg_type, pkt.data);
disks[disk]->write(offset, reg_type, pkt.data +
sizeof(uint16_t));
break;
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;
default:
if (req->size == sizeof(uint8_t)) {
disks[disk]->write(offset, reg_type, data);
if (pkt.size == sizeof(uint8_t)) {
disks[disk]->write(offset, reg_type, pkt.data);
} 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;
default:
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",
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_ARRAY(cmd_in_progress,
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
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
Param<Addr> addr;
SimObjectVectorParam<IdeDisk *> disks;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
SimObjectParam<Bus *> pio_bus;
SimObjectParam<Bus *> dma_bus;
Param<Tick> pio_latency;
SimObjectParam<HierParams *> hier;
SimObjectVectorParam<IdeDisk *> disks;
END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(addr, "Device Address"),
INIT_PARAM(disks, "IDE disks attached to this controller"),
INIT_PARAM(mmu, "Memory controller"),
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
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(hier, "Hierarchy global variables", &defaultHierParams)
INIT_PARAM(disks, "IDE disks attached to this controller")
END_INIT_SIM_OBJECT_PARAMS(IdeController)
@ -750,19 +821,15 @@ CREATE_SIM_OBJECT(IdeController)
{
IdeController::Params *params = new IdeController::Params;
params->name = getInstanceName();
params->mmu = mmu;
params->platform = platform;
params->system = system;
params->configSpace = configspace;
params->configData = configdata;
params->plat = platform;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
params->functionNum = pci_func;
params->pio_delay = pio_latency;
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);
}

View file

@ -70,6 +70,13 @@
#define IDE_CTRL_CONF_START 0x40
#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 {
COMMAND_BLOCK,
@ -77,13 +84,9 @@ enum IdeRegType {
BMI_BLOCK
};
class BaseInterface;
class Bus;
class HierParams;
class IdeDisk;
class IntrControl;
class PciConfigAll;
class PhysicalMemory;
class Platform;
/**
@ -191,10 +194,6 @@ class IdeController : public PciDev
{
/** Array of disk objects */
std::vector<IdeDisk *> disks;
Bus *pio_bus;
Bus *dma_bus;
Tick pio_latency;
HierParams *hier;
};
const Params *params() const { return (const Params *)_params; }
@ -202,26 +201,28 @@ class IdeController : public PciDev
IdeController(Params *p);
~IdeController();
virtual void writeConfig(int offset, int size, const uint8_t *data);
virtual void readConfig(int offset, int size, 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);
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);
/**
* Read a done field for a given target.
* @param req Contains the address of the field to read.
* @param data Return the field read.
* @return The fault condition of the access.
* @param pkt Packet describing what is to be read
* @return The amount of time to complete this request
*/
virtual Fault read(MemReqPtr &req, uint8_t *data);
virtual Tick read(Packet &pkt);
/**
* Write to the mmapped I/O control registers.
* @param req Contains the address to write to.
* @param data The data to write.
* @return The fault condition of the access.
* Write a done field for a given target.
* @param pkt Packet describing what is to be written
* @return The amount of time to complete this request
*/
virtual Fault write(MemReqPtr &req, const uint8_t *data);
virtual Tick write(Packet &pkt);
/**
* 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);
/**
* 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_

View file

@ -35,6 +35,7 @@
#include <deque>
#include <string>
#include "base/chunk_generator.hh"
#include "base/cprintf.hh" // csprintf
#include "base/trace.hh"
#include "dev/disk_image.hh"
@ -42,11 +43,7 @@
#include "dev/ide_ctrl.hh"
#include "dev/tsunami.hh"
#include "dev/tsunami_pchip.hh"
#include "mem/functional/physical.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 "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/sim_object.hh"
#include "sim/root.hh"
@ -55,11 +52,11 @@
using namespace std;
using namespace TheISA;
IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
IdeDisk::IdeDisk(const string &name, DiskImage *img,
int id, Tick delay)
: SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay),
dmaTransferEvent(this), dmaReadWaitEvent(this),
dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
: SimObject(name), ctrl(NULL), image(img), diskDelay(delay),
dmaTransferEvent(this), dmaReadCG(NULL), dmaReadWaitEvent(this),
dmaWriteCG(NULL), dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this)
{
// Reset the device state
@ -139,7 +136,6 @@ IdeDisk::reset(int id)
memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
dmaInterfaceBytes = 0;
curPrdAddr = 0;
curSector = 0;
cmdBytes = 0;
@ -188,29 +184,6 @@ IdeDisk::pciToDma(Addr pciAddr)
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
////
@ -339,29 +312,17 @@ IdeDisk::doDmaTransfer()
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState);
// first read the current PRD
if (dmaInterface) {
if (dmaInterface->busy()) {
// reschedule after waiting period
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
}
dmaInterface->doDMA(Read, curPrdAddr, sizeof(PrdEntry_t), curTick,
&dmaPrdReadEvent);
} else {
dmaPrdReadDone();
}
if (ctrl->dmaPending()) {
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else
ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent,
(uint8_t*)&curPrd.entry);
}
void
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,
"PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
@ -372,38 +333,49 @@ IdeDisk::dmaPrdReadDone()
curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
if (dmaRead)
doDmaRead();
doDmaDataRead();
else
doDmaWrite();
doDmaDataWrite();
}
void
IdeDisk::doDmaRead()
IdeDisk::doDmaDataRead()
{
/** @todo we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
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,
curTick + totalDiskDelay, &dmaReadEvent);
if (!dmaReadCG) {
// 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 {
// schedule dmaReadEvent with sectorDelay (dmaReadDone)
dmaReadEvent.schedule(curTick + totalDiskDelay);
assert(dmaReadCG->done());
delete dmaReadCG;
dmaReadCG = NULL;
dmaReadDone();
}
}
@ -411,63 +383,14 @@ void
IdeDisk::dmaReadDone()
{
Addr curAddr = 0, dmaAddr = 0;
uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0;
uint32_t bytesWritten = 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
for (bytesWritten = 0;
bytesWritten < curPrd.getByteCount();
for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
bytesWritten += SectorSize) {
cmdBytesLeft -= SectorSize;
writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
}
@ -482,107 +405,55 @@ IdeDisk::dmaReadDone()
}
void
IdeDisk::doDmaWrite()
IdeDisk::doDmaDataWrite()
{
/** @todo we need to figure out what the delay actually will be */
Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
uint32_t bytesRead = 0;
DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
diskDelay, totalDiskDelay);
if (dmaInterface) {
if (dmaInterface->busy()) {
// reschedule after waiting period
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
}
memset(dataBuffer, 0, MAX_DMA_SIZE);
assert(cmdBytesLeft <= MAX_DMA_SIZE);
while (bytesRead < curPrd.getByteCount()) {
readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
bytesRead += SectorSize;
cmdBytesLeft -= SectorSize;
}
Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
dmaWriteWaitEvent.schedule(curTick + totalDiskDelay);
}
uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
(uint32_t)curPrd.getByteCount());
void
IdeDisk::doDmaWrite()
{
dmaInterfaceBytes = bytesInPage;
dmaInterface->doDMA(WriteInvalidate, dmaAddr,
bytesInPage, curTick + totalDiskDelay,
&dmaWriteEvent);
if (!dmaWriteCG) {
// clear out the data buffer
dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
curPrd.getByteCount(), TheISA::PageBytes);
}
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 {
// schedule event with disk delay (dmaWriteDone)
dmaWriteEvent.schedule(curTick + totalDiskDelay);
assert(dmaWriteCG->done());
delete dmaWriteCG;
dmaWriteCG = NULL;
dmaWriteDone();
}
}
void
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
if (curPrd.getEOT()) {
assert(cmdBytesLeft == 0);
@ -1138,13 +1009,13 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_SCALAR(curPrd.entry.endOfTable);
SERIALIZE_SCALAR(curPrdAddr);
/** @todo need to serialized chunk generator stuff!! */
// Serialize current transfer related information
SERIALIZE_SCALAR(cmdBytesLeft);
SERIALIZE_SCALAR(cmdBytes);
SERIALIZE_SCALAR(drqBytesLeft);
SERIALIZE_SCALAR(curSector);
SERIALIZE_SCALAR(dmaRead);
SERIALIZE_SCALAR(dmaInterfaceBytes);
SERIALIZE_SCALAR(intrPending);
SERIALIZE_ENUM(devState);
SERIALIZE_ENUM(dmaState);
@ -1190,13 +1061,13 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
UNSERIALIZE_SCALAR(curPrdAddr);
/** @todo need to serialized chunk generator stuff!! */
// Unserialize current transfer related information
UNSERIALIZE_SCALAR(cmdBytes);
UNSERIALIZE_SCALAR(cmdBytesLeft);
UNSERIALIZE_SCALAR(drqBytesLeft);
UNSERIALIZE_SCALAR(curSector);
UNSERIALIZE_SCALAR(dmaRead);
UNSERIALIZE_SCALAR(dmaInterfaceBytes);
UNSERIALIZE_SCALAR(intrPending);
UNSERIALIZE_ENUM(devState);
UNSERIALIZE_ENUM(dmaState);
@ -1210,7 +1081,6 @@ static const char *DriveID_strings[] = { "master", "slave" };
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
SimObjectParam<DiskImage *> image;
SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<DriveID> driveID;
Param<int> delay;
@ -1219,7 +1089,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"),
INIT_PARAM(physmem, "Physical memory"),
INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
@ -1228,7 +1097,7 @@ END_INIT_SIM_OBJECT_PARAMS(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)

View file

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

View file

@ -105,23 +105,24 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
}
DmaPort::DmaPort(DmaDevice *dev)
: device(dev)
DmaPort::DmaPort(DmaDevice *dev, Platform *p)
: device(dev), platform(p), pendingCount(0)
{ }
bool
DmaPort::recvTiming(Packet &pkt)
{
completionEvent->schedule(curTick+1);
completionEvent = NULL;
if (pkt.senderState) {
DmaReqState *state;
state = (DmaReqState*)pkt.senderState;
state->completionEvent->schedule(pkt.time - pkt.req->getTime());
}
return Success;
}
DmaDevice::DmaDevice(Params *p)
: PioDevice(p)
{
dmaPort = new DmaPort(this);
}
: PioDevice(p), dmaPort(NULL)
{ }
void
DmaPort::SendEvent::process()
@ -140,8 +141,8 @@ DmaPort::recvRetry()
return pkt;
}
void
DmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
Event *event, uint8_t *data)
DmaPort::dmaAction(Command cmd, Addr addr, int size, Event *event,
uint8_t *data)
{
assert(event);
@ -161,8 +162,6 @@ DmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
// baseReq.nicReq = true;
baseReq.setTime(curTick);
completionEvent = event;
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
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
pkt->data = data ? data + prevSize : NULL ;
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);
}
}
@ -194,8 +201,12 @@ DmaPort::sendDma(Packet &pkt)
transmitList.push_back(&packet);
} else if (state == Atomic) {*/
sendAtomic(pkt);
completionEvent->schedule(pkt.time - pkt.req->getTime());
completionEvent = NULL;
if (pkt.senderState) {
DmaReqState *state = (DmaReqState*)pkt.senderState;
state->completionEvent->schedule(curTick + (pkt.time - pkt.req->getTime()) +1);
}
pendingCount--;
assert(pendingCount >= 0);
/* } else if (state == Functional) {
sendFunctional(pkt);
// Is this correct???

View file

@ -113,13 +113,28 @@ class PioPort : public Port
friend class PioPort::SendEvent;
};
struct DmaReqState
{
Event *completionEvent;
bool final;
DmaReqState(Event *ce, bool f)
: completionEvent(ce), final(f)
{}
};
class DmaPort : public Port
{
protected:
PioDevice *device;
DmaDevice *device;
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 Tick recvAtomic(Packet &pkt)
@ -152,13 +167,15 @@ class DmaPort : public Port
friend class DmaPort;
};
void dmaAction(Command cmd, DmaPort port, Addr addr, int size,
Event *event, uint8_t *data = NULL);
void sendDma(Packet &pkt);
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;
@ -286,13 +303,27 @@ class DmaDevice : public PioDevice
DmaDevice(Params *p);
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)
{
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;
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;
else
} else
return NULL;
}

View file

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

View file

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

View file

@ -39,20 +39,20 @@
#include "base/misc.hh"
#include "base/str.hh" // for to_number
#include "base/trace.hh"
#include "dev/pcidev.hh"
#include "dev/pciconfigall.hh"
#include "mem/bus/bus.hh"
#include "mem/functional/memory_control.hh"
#include "dev/pcidev.hh"
#include "dev/tsunamireg.h"
#include "mem/packet.hh"
#include "sim/builder.hh"
#include "sim/byteswap.hh"
#include "sim/param.hh"
#include "sim/root.hh"
#include "dev/tsunamireg.h"
using namespace std;
PciDev::PciDev(Params *p)
: DmaDevice(p->name, p->plat), _params(p), plat(p->plat),
configData(p->configData)
: DmaDevice(p), plat(p->platform), configData(p->configData),
pioDelay(p->pio_delay)
{
// copy the config data from the PciConfigData object
if (configData) {
@ -70,214 +70,180 @@ PciDev::PciDev(Params *p)
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
PciDev::readConfig(int offset, int size, uint8_t *data)
PciDev::readConfig(int offset, uint8_t *data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
switch(size) {
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");
}
*data = config.data[offset];
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, size,
*(uint32_t*)data);
"read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, *data);
}
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)
panic("Device specific PCI config space not implemented!\n");
uint8_t &data8 = *(uint8_t*)data;
uint16_t &data16 = *(uint16_t*)data;
uint32_t &data32 = *(uint32_t*)data;
*data = *(uint16_t*)&config.data[offset];
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
params()->deviceNum, params()->functionNum, offset, size, data32);
"read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, *data);
}
switch (size) {
case sizeof(uint8_t): // 1-byte access
switch (offset) {
case PCI0_INTERRUPT_LINE:
config.interruptLine = data8;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data8;
case PCI_LATENCY_TIMER:
config.latencyTimer = data8;
break;
/* Do nothing for these read-only registers */
case PCI0_INTERRUPT_PIN:
case PCI0_MINIMUM_GRANT:
case PCI0_MAXIMUM_LATENCY:
case PCI_CLASS_CODE:
case PCI_REVISION_ID:
break;
default:
panic("writing to a read only register");
}
void
PciDev::readConfig(int offset, uint32_t *data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
*data = *(uint32_t*)&config.data[offset];
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, *data);
}
void
PciDev::writeConfig(int offset, const uint8_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
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;
case sizeof(uint16_t): // 2-byte access
switch (offset) {
case PCI_COMMAND:
config.command = data16;
case PCI_STATUS:
config.status = data16;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data16;
break;
default:
panic("writing to a read only register");
}
/* Do nothing for these read-only registers */
case PCI0_INTERRUPT_PIN:
case PCI0_MINIMUM_GRANT:
case PCI0_MAXIMUM_LATENCY:
case PCI_CLASS_CODE:
case PCI_REVISION_ID:
break;
default:
panic("writing to a read only register");
}
}
case sizeof(uint32_t): // 4-byte access
switch (offset) {
case PCI0_BASE_ADDR0:
case PCI0_BASE_ADDR1:
case PCI0_BASE_ADDR2:
case PCI0_BASE_ADDR3:
case PCI0_BASE_ADDR4:
case PCI0_BASE_ADDR5:
void
PciDev::writeConfig(int offset, const uint16_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
uint32_t barnum, bar_mask;
Addr base_addr, base_size, space_base;
DPRINTF(PCIDEV,
"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
// value of the bar to size of memory it needs
if (letoh(data32) == 0xffffffff) {
// This is I/O Space, bottom two bits are read only
void
PciDev::writeConfig(int offset, const uint32_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
config.baseAddr[barnum] = letoh(
(~(BARSize[barnum] - 1) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
} else {
MemoryController *mmu = params()->mmu;
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: 4 data: %#x\n",
params()->deviceNum, params()->functionNum, offset, data);
config.baseAddr[barnum] = letoh(
(letoh(data32) & ~bar_mask) |
switch (offset) {
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));
} else {
config.baseAddr[barnum] = letoh(
(letoh(data) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
base_addr = (letoh(data32) & ~bar_mask) + space_base;
base_size = BARSize[barnum];
if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
base_addr = (letoh(data) & ~bar_mask) + space_base;
base_size = BARSize[barnum];
BARAddrs[barnum] = base_addr;
// It's never been set
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;
}
pioPort->sendStatusChange(Port::RangeChange);
}
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;
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:
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(config.data,
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

View file

@ -44,7 +44,6 @@
#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
class PciConfigAll;
class MemoryController;
/**
@ -85,12 +84,8 @@ class PciConfigData : public SimObject
class PciDev : public DmaDevice
{
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 read comes to this particular device/function.
@ -111,13 +106,13 @@ class PciDev : public DmaDevice
/** The function number */
uint32_t functionNum;
/** The latency for pio accesses. */
Tick pio_delay;
};
protected:
Params *_params;
public:
const Params *params() const { return _params; }
const Params *params() const { return (const Params *)_params; }
protected:
/** The current config space. Unlike the PciConfigData this is
@ -164,6 +159,7 @@ class PciDev : public DmaDevice
protected:
Platform *plat;
PciConfigData *configData;
Tick pioDelay;
public:
Addr pciToDma(Addr pciAddr) const
@ -181,7 +177,11 @@ class PciDev : public DmaDevice
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
* config file object PCIConfigData and registers the device with
@ -189,39 +189,6 @@ class PciDev : public DmaDevice
*/
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
* 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 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 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.
@ -256,43 +227,4 @@ class PciDev : public DmaDevice
*/
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__

View file

@ -97,21 +97,30 @@ Bus::recvStatusChange(Port::Status status, int id)
Port *port = interfaces[id];
AddrRangeList ranges;
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);
// not dealing with snooping yet either
assert(snoops.size() == 0);
// or multiple ranges
assert(ranges.size() == 1);
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
DevMap dm;
dm.portId = id;
dm.range = *iter;
DevMap dm;
dm.portId = id;
dm.range = ranges.front();
DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
dm.range.end, id);
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());
}

View file

@ -92,7 +92,7 @@ struct Packet
// assert(dynamic_cast<Foo>) etc.
/** 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.
/** 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";
}
PhysicalMemory::PhysicalMemory(const string &n)
: MemObject(n), base_addr(0), pmem_addr(NULL), port(NULL)
PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
: MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
{
// Hardcoded to 128 MB for now.
pmem_size = 1 << 27;
@ -137,6 +137,7 @@ Tick
PhysicalMemory::doAtomicAccess(Packet &pkt)
{
doFunctionalAccess(pkt);
pkt.time = curTick + lat;
return curTick + lat;
}
@ -344,20 +345,22 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
Param<string> file;
Param<Range<Addr> > range;
Param<Tick> latency;
END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
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)
CREATE_SIM_OBJECT(PhysicalMemory)
{
return new PhysicalMemory(getInstanceName());
return new PhysicalMemory(getInstanceName(), latency);
}
REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)

View file

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

View file

@ -12,3 +12,7 @@ class BasicPioDevice(PioDevice):
abstract = True
pio_addr = Param.Addr("Device Address")
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")
driveID = Param.IdeID('master', "Drive ID")
image = Param.DiskImage("Disk image")
physmem = Param.PhysicalMemory(Parent.any, "Physical memory")
class IdeController(PciDevice):
type = 'IdeController'

View file

@ -1,6 +1,5 @@
from m5 import *
from Device import BasicPioDevice
#, DmaDevice
from Device import BasicPioDevice, DmaDevice
class PciConfigData(SimObject):
type = 'PciConfigData'
@ -42,15 +41,15 @@ class PciConfigData(SimObject):
class PciConfigAll(BasicPioDevice):
type = 'PciConfigAll'
#class PciDevice(DmaDevice):
# type = 'PciDevice'
# abstract = True
# addr = 0xffffffffL
# pci_bus = Param.Int("PCI bus")
# pci_dev = Param.Int("PCI device number")
# pci_func = Param.Int("PCI function code")
# configdata = Param.PciConfigData(Parent.any, "PCI Config data")
# configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
#
#class PciFake(PciDevice):
# type = 'PciFake'
class PciDevice(DmaDevice):
type = 'PciDevice'
abstract = True
pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number")
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")
configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
class PciFake(PciDevice):
type = 'PciFake'

View file

@ -1,7 +1,8 @@
from m5 import *
from Memory import Memory
from MemObject import *
class PhysicalMemory(Memory):
class PhysicalMemory(MemObject):
type = 'PhysicalMemory'
range = Param.AddrRange("Device Address")
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
#if defined(linux)
#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
#include <machine/endian.h>
#endif
@ -47,6 +51,9 @@
static inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(linux)
return bswap_64(x);
#else
return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
((uint64_t)(x) & 0xff00ULL) << 40 |
((uint64_t)(x) & 0xff0000ULL) << 24 |
@ -55,22 +62,30 @@ swap_byte64(uint64_t x)
((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
}
static inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(linux)
return bswap_32(x);
#else
return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
((uint32_t)(x) & 0xff000000) >> 24);
#endif
}
static inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(linux)
return bswap_16(x);
#else
return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
((uint16_t)(x) & 0xff00) >> 8);
#endif
}
//This lets the compiler figure out how to call the swap_byte functions above