diff --git a/SConscript b/SConscript index 378f4db1f..e41939ba3 100644 --- a/SConscript +++ b/SConscript @@ -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 diff --git a/base/chunk_generator.hh b/base/chunk_generator.hh index 1dca50db4..4f708bd4b 100644 --- a/base/chunk_generator.hh +++ b/base/chunk_generator.hh @@ -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? diff --git a/configs/test/fs.py b/configs/test/fs.py index d2e5381f0..6608aafa7 100644 --- a/configs/test/fs.py +++ b/configs/test/fs.py @@ -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() diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index fed604867..f0fc7596e 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -31,7 +31,6 @@ #include #include -#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(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 §ion) 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; - SimObjectVectorParam disks; - SimObjectParam mmu; + SimObjectParam system; + SimObjectParam platform; SimObjectParam configspace; SimObjectParam configdata; - SimObjectParam platform; Param pci_bus; Param pci_dev; Param pci_func; - SimObjectParam pio_bus; - SimObjectParam dma_bus; Param pio_latency; - SimObjectParam hier; + SimObjectVectorParam 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); } diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh index 0fbaf9207..a074f4f97 100644 --- a/dev/ide_ctrl.hh +++ b/dev/ide_ctrl.hh @@ -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 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 §ion); - /** - * 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_ diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index 41400c590..f1aafbc6d 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -35,6 +35,7 @@ #include #include +#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 §ion) 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 image; - SimObjectParam physmem; SimpleEnumParam driveID; Param 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) diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh index a656ca464..3d67abece 100644 --- a/dev/ide_disk.hh +++ b/dev/ide_disk.hh @@ -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 *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 *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; EventWrapper dmaTransferEvent; + void doDmaDataRead(); + void doDmaRead(); + ChunkGenerator *dmaReadCG; friend class EventWrapper; EventWrapper dmaReadWaitEvent; + void doDmaDataWrite(); + void doDmaWrite(); + ChunkGenerator *dmaWriteCG; friend class EventWrapper; EventWrapper 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. diff --git a/dev/io_device.cc b/dev/io_device.cc index a2e5a8a0d..4a84b6817 100644 --- a/dev/io_device.cc +++ b/dev/io_device.cc @@ -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??? diff --git a/dev/io_device.hh b/dev/io_device.hh index 5379a664c..bc0160c46 100644 --- a/dev/io_device.hh +++ b/dev/io_device.hh @@ -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 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; } diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index 86a505b9a..fa6b35f77 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -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; } diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh index b2034594c..2393b445e 100644 --- a/dev/pciconfigall.hh +++ b/dev/pciconfigall.hh @@ -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. diff --git a/dev/pcidev.cc b/dev/pcidev.cc index a05ee3803..c40ef62e4 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -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 §ion) 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 diff --git a/dev/pcidev.hh b/dev/pcidev.hh index bdfc6b932..fc4773908 100644 --- a/dev/pcidev.hh +++ b/dev/pcidev.hh @@ -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 §ion); }; - -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__ diff --git a/mem/bus.cc b/mem/bus.cc index 5e84beb83..86e834894 100644 --- a/mem/bus.cc +++ b/mem/bus.cc @@ -97,21 +97,30 @@ Bus::recvStatusChange(Port::Status status, int id) Port *port = interfaces[id]; AddrRangeList ranges; AddrRangeList snoops; + AddrRangeIter iter; + std::vector::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()); } diff --git a/mem/packet.hh b/mem/packet.hh index 843d34ac0..79fe0ea06 100644 --- a/mem/packet.hh +++ b/mem/packet.hh @@ -92,7 +92,7 @@ struct Packet // assert(dynamic_cast) 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) etc. /** A pointer to the data being transfered. It can be differnt sizes diff --git a/mem/physical.cc b/mem/physical.cc index b00935990..a15a59106 100644 --- a/mem/physical.cc +++ b/mem/physical.cc @@ -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 file; Param > range; + Param 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) diff --git a/mem/physical.hh b/mem/physical.hh index ce0a2099c..f87683c45 100644 --- a/mem/physical.hh +++ b/mem/physical.hh @@ -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: diff --git a/python/m5/objects/Device.py b/python/m5/objects/Device.py index cda3b1824..2a71bbc65 100644 --- a/python/m5/objects/Device.py +++ b/python/m5/objects/Device.py @@ -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 diff --git a/python/m5/objects/Ide.py b/python/m5/objects/Ide.py index 6855ec653..2403e6d36 100644 --- a/python/m5/objects/Ide.py +++ b/python/m5/objects/Ide.py @@ -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' diff --git a/python/m5/objects/Pci.py b/python/m5/objects/Pci.py index f2ccce09f..85cefcd44 100644 --- a/python/m5/objects/Pci.py +++ b/python/m5/objects/Pci.py @@ -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' diff --git a/python/m5/objects/PhysicalMemory.py b/python/m5/objects/PhysicalMemory.py index b69c969cb..e59e94e9b 100644 --- a/python/m5/objects/PhysicalMemory.py +++ b/python/m5/objects/PhysicalMemory.py @@ -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") diff --git a/sim/byteswap.hh b/sim/byteswap.hh index 0dd0ba827..a8c5da9d7 100644 --- a/sim/byteswap.hh +++ b/sim/byteswap.hh @@ -38,6 +38,10 @@ // This lets us figure out what the byte order of the host system is #if defined(linux) #include +// 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 #else #include #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