ide_ctrl.cc revision 849
16019Shines@cs.fsu.edu/* 212509Schuan.zhu@arm.com * Copyright (c) 2003 The Regents of The University of Michigan 37189Sgblack@eecs.umich.edu * All rights reserved. 47189Sgblack@eecs.umich.edu * 57189Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67189Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77189Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87189Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97189Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107189Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117189Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127189Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137189Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu */ 286019Shines@cs.fsu.edu 296019Shines@cs.fsu.edu#include <cstddef> 306019Shines@cs.fsu.edu#include <cstdlib> 316019Shines@cs.fsu.edu#include <string> 326019Shines@cs.fsu.edu#include <vector> 336019Shines@cs.fsu.edu 346019Shines@cs.fsu.edu#include "base/trace.hh" 356019Shines@cs.fsu.edu#include "cpu/intr_control.hh" 366019Shines@cs.fsu.edu#include "dev/dma.hh" 376019Shines@cs.fsu.edu#include "dev/pcireg.h" 386019Shines@cs.fsu.edu#include "dev/pciconfigall.hh" 396019Shines@cs.fsu.edu#include "dev/ide_disk.hh" 406019Shines@cs.fsu.edu#include "dev/ide_ctrl.hh" 416735Sgblack@eecs.umich.edu#include "dev/tsunami_cchip.hh" 426735Sgblack@eecs.umich.edu#include "mem/bus/bus.hh" 4310037SARM gem5 Developers#include "mem/bus/pio_interface.hh" 4410037SARM gem5 Developers#include "mem/bus/pio_interface_impl.hh" 456019Shines@cs.fsu.edu#include "mem/bus/dma_interface.hh" 466019Shines@cs.fsu.edu#include "dev/tsunami.hh" 476019Shines@cs.fsu.edu#include "mem/functional_mem/memory_control.hh" 486019Shines@cs.fsu.edu#include "mem/functional_mem/physical_memory.hh" 496019Shines@cs.fsu.edu#include "sim/builder.hh" 507362Sgblack@eecs.umich.edu#include "sim/sim_object.hh" 5110037SARM gem5 Developers 526735Sgblack@eecs.umich.eduusing namespace std; 5312334Sgabeblack@google.com 546019Shines@cs.fsu.edu//// 558782Sgblack@eecs.umich.edu// Initialization and destruction 566019Shines@cs.fsu.edu//// 576019Shines@cs.fsu.edu 586019Shines@cs.fsu.eduIdeController::IdeController(const string &name, IntrControl *ic, 596019Shines@cs.fsu.edu const vector<IdeDisk *> &new_disks, 606019Shines@cs.fsu.edu MemoryController *mmu, PciConfigAll *cf, 6111294Sandreas.hansson@arm.com PciConfigData *cd, Tsunami *t, uint32_t bus_num, 626019Shines@cs.fsu.edu uint32_t dev_num, uint32_t func_num, 637362Sgblack@eecs.umich.edu Bus *host_bus, HierParams *hier) 646019Shines@cs.fsu.edu : PciDev(name, mmu, cf, cd, bus_num, dev_num, func_num), tsunami(t) 656019Shines@cs.fsu.edu{ 6610037SARM gem5 Developers // put back pointer into Tsunami 6710037SARM gem5 Developers tsunami->disk_controller = this; 6810037SARM gem5 Developers 6910037SARM gem5 Developers // initialize the PIO interface addresses 7010037SARM gem5 Developers pri_cmd_addr = 0; 7110037SARM gem5 Developers pri_cmd_size = BARSize[0]; 7210037SARM gem5 Developers 7310037SARM gem5 Developers pri_ctrl_addr = 0; 7410037SARM gem5 Developers pri_ctrl_size = BARSize[1]; 7510037SARM gem5 Developers 7612402Sgiacomo.travaglini@arm.com sec_cmd_addr = 0; 7712402Sgiacomo.travaglini@arm.com sec_cmd_size = BARSize[2]; 786735Sgblack@eecs.umich.edu 7910037SARM gem5 Developers sec_ctrl_addr = 0; 806735Sgblack@eecs.umich.edu sec_ctrl_size = BARSize[3]; 816019Shines@cs.fsu.edu 8210037SARM gem5 Developers // initialize the bus master interface (BMI) address to be configured 8310037SARM gem5 Developers // via PCI 8410037SARM gem5 Developers bmi_addr = 0; 8510037SARM gem5 Developers bmi_size = BARSize[4]; 8610037SARM gem5 Developers 877362Sgblack@eecs.umich.edu // zero out all of the registers 8810037SARM gem5 Developers memset(bmi_regs, 0, sizeof(bmi_regs)); 8910037SARM gem5 Developers memset(pci_regs, 0, sizeof(pci_regs)); 9010037SARM gem5 Developers 9110037SARM gem5 Developers // setup initial values 9210037SARM gem5 Developers *(uint32_t *)&pci_regs[IDETIM] = 0x80008000; // enable both channels 9310037SARM gem5 Developers *(uint8_t *)&bmi_regs[BMIS0] = 0x60; 9410037SARM gem5 Developers *(uint8_t *)&bmi_regs[BMIS1] = 0x60; 9510037SARM gem5 Developers 9610037SARM gem5 Developers // reset all internal variables 9710037SARM gem5 Developers io_enabled = false; 9810037SARM gem5 Developers bm_enabled = false; 9910037SARM gem5 Developers memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); 10010037SARM gem5 Developers 10110037SARM gem5 Developers // create the PIO and DMA interfaces 10210037SARM gem5 Developers if (host_bus) { 1037611SGene.Wu@arm.com pioInterface = newPioInterface(name, hier, host_bus, this, 10410037SARM gem5 Developers &IdeController::cacheAccess); 10510037SARM gem5 Developers 10610037SARM gem5 Developers dmaInterface = new DMAInterface<Bus>(name + ".dma", host_bus, 10710037SARM gem5 Developers host_bus, 1); 10810037SARM gem5 Developers } 10910037SARM gem5 Developers 11010037SARM gem5 Developers // setup the disks attached to controller 11110037SARM gem5 Developers memset(disks, 0, sizeof(IdeDisk *) * 4); 11210037SARM gem5 Developers 11310037SARM gem5 Developers if (new_disks.size() > 3) 11410037SARM gem5 Developers panic("IDE controllers support a maximum of 4 devices attached!\n"); 11510037SARM gem5 Developers 11610037SARM gem5 Developers for (int i = 0; i < new_disks.size(); i++) { 11710037SARM gem5 Developers disks[i] = new_disks[i]; 11810037SARM gem5 Developers disks[i]->setController(this, dmaInterface); 11910037SARM gem5 Developers } 12010037SARM gem5 Developers} 12110037SARM gem5 Developers 12210037SARM gem5 DevelopersIdeController::~IdeController() 12310037SARM gem5 Developers{ 12410037SARM gem5 Developers for (int i = 0; i < 4; i++) 12510037SARM gem5 Developers if (disks[i]) 12610037SARM gem5 Developers delete disks[i]; 12710037SARM gem5 Developers} 12810037SARM gem5 Developers 12910037SARM gem5 Developers//// 13010037SARM gem5 Developers// Command completion 13110037SARM gem5 Developers//// 13210037SARM gem5 Developers 13310037SARM gem5 Developersvoid 13410037SARM gem5 DevelopersIdeController::setDmaComplete(IdeDisk *disk) 13510037SARM gem5 Developers{ 13610037SARM gem5 Developers int diskNum = getDisk(disk); 13710037SARM gem5 Developers 13810037SARM gem5 Developers if (diskNum < 0) 13910037SARM gem5 Developers panic("Unable to find disk based on pointer %#x\n", disk); 14010037SARM gem5 Developers 1417362Sgblack@eecs.umich.edu if (diskNum < 2) { 1427362Sgblack@eecs.umich.edu // clear the start/stop bit in the command register 1436735Sgblack@eecs.umich.edu bmi_regs[BMIC0] &= ~SSBM; 1446735Sgblack@eecs.umich.edu // clear the bus master active bit in the status register 1456735Sgblack@eecs.umich.edu bmi_regs[BMIS0] &= ~BMIDEA; 14610037SARM gem5 Developers // set the interrupt bit 1476735Sgblack@eecs.umich.edu bmi_regs[BMIS0] |= IDEINTS; 14810037SARM gem5 Developers } else { 14910037SARM gem5 Developers // clear the start/stop bit in the command register 15010037SARM gem5 Developers bmi_regs[BMIC1] &= ~SSBM; 15110037SARM gem5 Developers // clear the bus master active bit in the status register 15210037SARM gem5 Developers bmi_regs[BMIS1] &= ~BMIDEA; 15310037SARM gem5 Developers // set the interrupt bit 15410037SARM gem5 Developers bmi_regs[BMIS1] |= IDEINTS; 1556735Sgblack@eecs.umich.edu } 15610037SARM gem5 Developers} 1576735Sgblack@eecs.umich.edu 1586735Sgblack@eecs.umich.edu//// 15910037SARM gem5 Developers// Interrupt handling 16010037SARM gem5 Developers//// 16110037SARM gem5 Developers 16210037SARM gem5 Developersvoid 16310037SARM gem5 DevelopersIdeController::intrPost() 16410037SARM gem5 Developers{ 16510037SARM gem5 Developers tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine); 1666735Sgblack@eecs.umich.edu} 1676735Sgblack@eecs.umich.edu 16810037SARM gem5 Developersvoid 16910037SARM gem5 DevelopersIdeController::intrClear() 17010037SARM gem5 Developers{ 17110037SARM gem5 Developers tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); 17210037SARM gem5 Developers} 1736735Sgblack@eecs.umich.edu 17412517Srekai.gonzalezalberquilla@arm.com//// 17512517Srekai.gonzalezalberquilla@arm.com// Bus timing and bus access functions 17612517Srekai.gonzalezalberquilla@arm.com//// 17712517Srekai.gonzalezalberquilla@arm.com 17812517Srekai.gonzalezalberquilla@arm.comTick 17912517Srekai.gonzalezalberquilla@arm.comIdeController::cacheAccess(MemReqPtr &req) 18012517Srekai.gonzalezalberquilla@arm.com{ 18112517Srekai.gonzalezalberquilla@arm.com // @todo Add more accurate timing to cache access 18212517Srekai.gonzalezalberquilla@arm.com return curTick + 1000; 18312517Srekai.gonzalezalberquilla@arm.com} 18412517Srekai.gonzalezalberquilla@arm.com 18512517Srekai.gonzalezalberquilla@arm.com//// 18612517Srekai.gonzalezalberquilla@arm.com// Read and write handling 18712517Srekai.gonzalezalberquilla@arm.com//// 18812517Srekai.gonzalezalberquilla@arm.com 18912517Srekai.gonzalezalberquilla@arm.comvoid 1906735Sgblack@eecs.umich.eduIdeController::ReadConfig(int offset, int size, uint8_t *data) 1916735Sgblack@eecs.umich.edu{ 19210037SARM gem5 Developers Addr origOffset = offset; 19310537Sandreas.hansson@arm.com 19412402Sgiacomo.travaglini@arm.com if (offset < PCI_DEVICE_SPECIFIC) { 19510037SARM gem5 Developers PciDev::ReadConfig(offset, size, data); 19610037SARM gem5 Developers } else { 19710037SARM gem5 Developers if (offset >= PCI_IDE_TIMING && offset < (PCI_IDE_TIMING + 4)) { 19810037SARM gem5 Developers offset -= PCI_IDE_TIMING; 19910037SARM gem5 Developers offset += IDETIM; 20010037SARM gem5 Developers 20110037SARM gem5 Developers if ((offset + size) > (IDETIM + 4)) 20210037SARM gem5 Developers panic("PCI read of IDETIM with invalid size\n"); 20310417Sandreas.hansson@arm.com } else if (offset == PCI_SLAVE_TIMING) { 20412176Sandreas.sandberg@arm.com offset -= PCI_SLAVE_TIMING; 20510417Sandreas.hansson@arm.com offset += SIDETIM; 20610417Sandreas.hansson@arm.com 20710037SARM gem5 Developers if ((offset + size) > (SIDETIM + 1)) 2086735Sgblack@eecs.umich.edu panic("PCI read of SIDETIM with invalid size\n"); 20910037SARM gem5 Developers } else if (offset == PCI_UDMA33_CTRL) { 21012511Schuan.zhu@arm.com offset -= PCI_UDMA33_CTRL; 2116735Sgblack@eecs.umich.edu offset += UDMACTL; 21210037SARM gem5 Developers 21310037SARM gem5 Developers if ((offset + size) > (UDMACTL + 1)) 21410037SARM gem5 Developers panic("PCI read of UDMACTL with invalid size\n"); 21510037SARM gem5 Developers } else if (offset >= PCI_UDMA33_TIMING && 21610037SARM gem5 Developers offset < (PCI_UDMA33_TIMING + 2)) { 21710037SARM gem5 Developers offset -= PCI_UDMA33_TIMING; 21810037SARM gem5 Developers offset += UDMATIM; 21910037SARM gem5 Developers 22010037SARM gem5 Developers if ((offset + size) > (UDMATIM + 2)) 22110037SARM gem5 Developers panic("PCI read of UDMATIM with invalid size\n"); 22210037SARM gem5 Developers } else { 22310037SARM gem5 Developers panic("PCI read of unimplemented register: %x\n", offset); 22410037SARM gem5 Developers } 2256019Shines@cs.fsu.edu 2266019Shines@cs.fsu.edu memcpy((void *)data, (void *)&pci_regs[offset], size); 2276735Sgblack@eecs.umich.edu } 2287362Sgblack@eecs.umich.edu 2296019Shines@cs.fsu.edu DPRINTF(IdeCtrl, "IDE PCI read offset: %#x (%#x) size: %#x data: %#x\n", 2306735Sgblack@eecs.umich.edu origOffset, offset, size, *(uint32_t *)data); 2316735Sgblack@eecs.umich.edu} 2326735Sgblack@eecs.umich.edu 2336019Shines@cs.fsu.eduvoid 23410037SARM gem5 DevelopersIdeController::WriteConfig(int offset, int size, uint32_t data) 23510037SARM gem5 Developers{ 23612176Sandreas.sandberg@arm.com DPRINTF(IdeCtrl, "IDE PCI write offset: %#x size: %#x data: %#x\n", 23712176Sandreas.sandberg@arm.com offset, size, data); 23812176Sandreas.sandberg@arm.com 23910037SARM gem5 Developers // do standard write stuff if in standard PCI space 24012511Schuan.zhu@arm.com if (offset < PCI_DEVICE_SPECIFIC) { 24110037SARM gem5 Developers PciDev::WriteConfig(offset, size, data); 24212176Sandreas.sandberg@arm.com } else { 24312176Sandreas.sandberg@arm.com if (offset >= PCI_IDE_TIMING && offset < (PCI_IDE_TIMING + 4)) { 24412176Sandreas.sandberg@arm.com offset -= PCI_IDE_TIMING; 24512176Sandreas.sandberg@arm.com offset += IDETIM; 24612176Sandreas.sandberg@arm.com 24712176Sandreas.sandberg@arm.com if ((offset + size) > (IDETIM + 4)) 24812176Sandreas.sandberg@arm.com panic("PCI write to IDETIM with invalid size\n"); 24912176Sandreas.sandberg@arm.com } else if (offset == PCI_SLAVE_TIMING) { 25012176Sandreas.sandberg@arm.com offset -= PCI_SLAVE_TIMING; 25112176Sandreas.sandberg@arm.com offset += SIDETIM; 25212176Sandreas.sandberg@arm.com 25312176Sandreas.sandberg@arm.com if ((offset + size) > (SIDETIM + 1)) 25412176Sandreas.sandberg@arm.com panic("PCI write to SIDETIM with invalid size\n"); 25512176Sandreas.sandberg@arm.com } else if (offset == PCI_UDMA33_CTRL) { 25612176Sandreas.sandberg@arm.com offset -= PCI_UDMA33_CTRL; 25712176Sandreas.sandberg@arm.com offset += UDMACTL; 25812176Sandreas.sandberg@arm.com 25912176Sandreas.sandberg@arm.com if ((offset + size) > (UDMACTL + 1)) 2606019Shines@cs.fsu.edu panic("PCI write to UDMACTL with invalid size\n"); 2616019Shines@cs.fsu.edu } else if (offset >= PCI_UDMA33_TIMING && 2627400SAli.Saidi@ARM.com offset < (PCI_UDMA33_TIMING + 2)) { 2637400SAli.Saidi@ARM.com offset -= PCI_UDMA33_TIMING; 2647400SAli.Saidi@ARM.com offset += UDMATIM; 26510417Sandreas.hansson@arm.com 26612176Sandreas.sandberg@arm.com if ((offset + size) > (UDMATIM + 2)) 2677400SAli.Saidi@ARM.com panic("PCI write to UDMATIM with invalid size\n"); 2687189Sgblack@eecs.umich.edu } else { 2697362Sgblack@eecs.umich.edu panic("PCI write to unimplemented register: %x\n", offset); 2707189Sgblack@eecs.umich.edu } 2717189Sgblack@eecs.umich.edu 2727189Sgblack@eecs.umich.edu memcpy((void *)&pci_regs[offset], (void *)&data, size); 2737640Sgblack@eecs.umich.edu } 27410037SARM gem5 Developers 27510205SAli.Saidi@ARM.com if (offset == PCI_COMMAND) { 2767189Sgblack@eecs.umich.edu if (config.data[offset] & IOSE) 2777189Sgblack@eecs.umich.edu io_enabled = true; 2787189Sgblack@eecs.umich.edu else 2797189Sgblack@eecs.umich.edu io_enabled = false; 2807640Sgblack@eecs.umich.edu 2817640Sgblack@eecs.umich.edu if (config.data[offset] & BME) 28210037SARM gem5 Developers bm_enabled = true; 28310205SAli.Saidi@ARM.com else 28410205SAli.Saidi@ARM.com bm_enabled = false; 28510037SARM gem5 Developers 28610205SAli.Saidi@ARM.com } else if (data != 0xffffffff) { 28710205SAli.Saidi@ARM.com switch (offset) { 28810037SARM gem5 Developers case PCI0_BASE_ADDR0: 28910205SAli.Saidi@ARM.com pri_cmd_addr = BARAddrs[0]; 29010205SAli.Saidi@ARM.com if (pioInterface) 2918782Sgblack@eecs.umich.edu pioInterface->addAddrRange(pri_cmd_addr, 2927189Sgblack@eecs.umich.edu pri_cmd_addr + pri_cmd_size - 1); 29310417Sandreas.hansson@arm.com 29412176Sandreas.sandberg@arm.com pri_cmd_addr = ((pri_cmd_addr | 0xf0000000000) & PA_IMPL_MASK); 29512176Sandreas.sandberg@arm.com break; 29612176Sandreas.sandberg@arm.com 29712176Sandreas.sandberg@arm.com case PCI0_BASE_ADDR1: 2987189Sgblack@eecs.umich.edu pri_ctrl_addr = BARAddrs[1]; 2997189Sgblack@eecs.umich.edu if (pioInterface) 3007362Sgblack@eecs.umich.edu pioInterface->addAddrRange(pri_ctrl_addr, 3017197Sgblack@eecs.umich.edu pri_ctrl_addr + pri_ctrl_size - 1); 3027197Sgblack@eecs.umich.edu 30310037SARM gem5 Developers pri_ctrl_addr = ((pri_ctrl_addr | 0xf0000000000) & PA_IMPL_MASK); 3047197Sgblack@eecs.umich.edu break; 30510037SARM gem5 Developers 30610037SARM gem5 Developers case PCI0_BASE_ADDR2: 30710037SARM gem5 Developers sec_cmd_addr = BARAddrs[2]; 30810037SARM gem5 Developers if (pioInterface) 3098782Sgblack@eecs.umich.edu pioInterface->addAddrRange(sec_cmd_addr, 3107197Sgblack@eecs.umich.edu sec_cmd_addr + sec_cmd_size - 1); 31110417Sandreas.hansson@arm.com 31212176Sandreas.sandberg@arm.com sec_cmd_addr = ((sec_cmd_addr | 0xf0000000000) & PA_IMPL_MASK); 31312176Sandreas.sandberg@arm.com break; 31412176Sandreas.sandberg@arm.com 31512176Sandreas.sandberg@arm.com case PCI0_BASE_ADDR3: 31610037SARM gem5 Developers sec_ctrl_addr = BARAddrs[3]; 31710037SARM gem5 Developers if (pioInterface) 31810037SARM gem5 Developers pioInterface->addAddrRange(sec_ctrl_addr, 31910037SARM gem5 Developers sec_ctrl_addr + sec_ctrl_size - 1); 32010037SARM gem5 Developers 32110037SARM gem5 Developers sec_ctrl_addr = ((sec_ctrl_addr | 0xf0000000000) & PA_IMPL_MASK); 32210037SARM gem5 Developers break; 32310037SARM gem5 Developers 32410037SARM gem5 Developers case PCI0_BASE_ADDR4: 32510417Sandreas.hansson@arm.com bmi_addr = BARAddrs[4]; 32612176Sandreas.sandberg@arm.com if (pioInterface) 32712176Sandreas.sandberg@arm.com pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1); 32812176Sandreas.sandberg@arm.com 32910037SARM gem5 Developers bmi_addr = ((bmi_addr | 0xf0000000000) & PA_IMPL_MASK); 33010037SARM gem5 Developers break; 33110037SARM gem5 Developers } 33210037SARM gem5 Developers } 33310037SARM gem5 Developers} 33410037SARM gem5 Developers 33510037SARM gem5 DevelopersFault 33610037SARM gem5 DevelopersIdeController::read(MemReqPtr &req, uint8_t *data) 33710037SARM gem5 Developers{ 33810037SARM gem5 Developers Addr offset; 33910037SARM gem5 Developers bool primary; 34010037SARM gem5 Developers bool byte; 34110037SARM gem5 Developers bool cmdBlk; 34210037SARM gem5 Developers RegType_t type; 34310037SARM gem5 Developers int disk; 34412509Schuan.zhu@arm.com 34512509Schuan.zhu@arm.com parseAddr(req->paddr, offset, primary, type); 34612176Sandreas.sandberg@arm.com byte = (req->size == sizeof(uint8_t)) ? true : false; 34710037SARM gem5 Developers cmdBlk = (type == COMMAND_BLOCK) ? true : false; 34810037SARM gem5 Developers 34910037SARM gem5 Developers if (!io_enabled) 35010037SARM gem5 Developers return No_Fault; 35110037SARM gem5 Developers 35210037SARM gem5 Developers // sanity check the size (allows byte, word, or dword access) 35310037SARM gem5 Developers if (req->size != sizeof(uint8_t) && req->size != sizeof(uint16_t) && 35410037SARM gem5 Developers req->size != sizeof(uint32_t)) 35510037SARM gem5 Developers panic("IDE controller read of invalid size: %#x\n", req->size); 35610037SARM gem5 Developers 35710037SARM gem5 Developers if (type != BMI_BLOCK) { 35810037SARM gem5 Developers assert(req->size != sizeof(uint32_t)); 35910037SARM gem5 Developers 36010037SARM gem5 Developers disk = getDisk(primary); 36110037SARM gem5 Developers if (disks[disk]) 36212176Sandreas.sandberg@arm.com disks[disk]->read(offset, byte, cmdBlk, data); 36310037SARM gem5 Developers } else { 36410037SARM gem5 Developers memcpy((void *)data, &bmi_regs[offset], req->size); 36510037SARM gem5 Developers } 36610037SARM gem5 Developers 36710037SARM gem5 Developers DPRINTF(IdeCtrl, "IDE read from offset: %#x size: %#x data: %#x\n", 36810037SARM gem5 Developers offset, req->size, *(uint32_t *)data); 36911576SDylan.Johnson@ARM.com 37012176Sandreas.sandberg@arm.com return No_Fault; 37110037SARM gem5 Developers} 37210037SARM gem5 Developers 37310037SARM gem5 DevelopersFault 37410037SARM gem5 DevelopersIdeController::write(MemReqPtr &req, const uint8_t *data) 37510037SARM gem5 Developers{ 37610037SARM gem5 Developers Addr offset; 37710037SARM gem5 Developers bool primary; 37810037SARM gem5 Developers bool byte; 37910037SARM gem5 Developers bool cmdBlk; 38010037SARM gem5 Developers RegType_t type; 38110037SARM gem5 Developers int disk; 38210037SARM gem5 Developers 38310037SARM gem5 Developers parseAddr(req->paddr, offset, primary, type); 38410037SARM gem5 Developers byte = (req->size == sizeof(uint8_t)) ? true : false; 38510037SARM gem5 Developers cmdBlk = (type == COMMAND_BLOCK) ? true : false; 38612176Sandreas.sandberg@arm.com 3877197Sgblack@eecs.umich.edu DPRINTF(IdeCtrl, "IDE write from offset: %#x size: %#x data: %#x\n", 3887362Sgblack@eecs.umich.edu offset, req->size, *(uint32_t *)data); 3897362Sgblack@eecs.umich.edu 3907362Sgblack@eecs.umich.edu uint8_t oldVal, newVal; 3917362Sgblack@eecs.umich.edu 3927362Sgblack@eecs.umich.edu if (!io_enabled) 39310037SARM gem5 Developers return No_Fault; 39410037SARM gem5 Developers 39510037SARM gem5 Developers if (type == BMI_BLOCK && !bm_enabled) 39610037SARM gem5 Developers return No_Fault; 39710037SARM gem5 Developers 39810037SARM gem5 Developers if (type != BMI_BLOCK) { 3997362Sgblack@eecs.umich.edu // shadow the dev bit 40010037SARM gem5 Developers if (type == COMMAND_BLOCK && offset == IDE_SELECT_OFFSET) { 40110037SARM gem5 Developers uint8_t *devBit = (primary ? &dev[0] : &dev[1]); 40210037SARM gem5 Developers *devBit = ((*data & IDE_SELECT_DEV_BIT) ? 1 : 0); 40310037SARM gem5 Developers } 40410037SARM gem5 Developers 40510037SARM gem5 Developers assert(req->size != sizeof(uint32_t)); 4067362Sgblack@eecs.umich.edu 40710037SARM gem5 Developers disk = getDisk(primary); 40810037SARM gem5 Developers if (disks[disk]) 40910037SARM gem5 Developers disks[disk]->write(offset, byte, cmdBlk, data); 41010037SARM gem5 Developers } else { 41110037SARM gem5 Developers switch (offset) { 41210037SARM gem5 Developers // Bus master IDE command register 4137362Sgblack@eecs.umich.edu case BMIC1: 4147362Sgblack@eecs.umich.edu case BMIC0: 41510537Sandreas.hansson@arm.com if (req->size != sizeof(uint8_t)) 41610537Sandreas.hansson@arm.com panic("Invalid BMIC write size: %x\n", req->size); 41710537Sandreas.hansson@arm.com 41810537Sandreas.hansson@arm.com // select the current disk based on DEV bit 41910537Sandreas.hansson@arm.com disk = getDisk(primary); 42010037SARM gem5 Developers 4217362Sgblack@eecs.umich.edu oldVal = bmi_regs[offset]; 4227362Sgblack@eecs.umich.edu newVal = *data; 42310417Sandreas.hansson@arm.com 42412176Sandreas.sandberg@arm.com // if a DMA transfer is in progress, R/W control cannot change 42510037SARM gem5 Developers if (oldVal & SSBM) { 42612176Sandreas.sandberg@arm.com if ((oldVal & RWCON) ^ (newVal & RWCON)) { 42712176Sandreas.sandberg@arm.com (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON; 42812176Sandreas.sandberg@arm.com } 42912176Sandreas.sandberg@arm.com } 43012176Sandreas.sandberg@arm.com 43110037SARM gem5 Developers // see if the start/stop bit is being changed 4327362Sgblack@eecs.umich.edu if ((oldVal & SSBM) ^ (newVal & SSBM)) { 4337362Sgblack@eecs.umich.edu if (oldVal & SSBM) { 4347362Sgblack@eecs.umich.edu // stopping DMA transfer 4357362Sgblack@eecs.umich.edu DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 4367362Sgblack@eecs.umich.edu 43710037SARM gem5 Developers // clear the BMIDEA bit 43810037SARM gem5 Developers bmi_regs[offset + 0x2] &= ~BMIDEA; 43910037SARM gem5 Developers 4407362Sgblack@eecs.umich.edu if (disks[disk] == NULL) 44110037SARM gem5 Developers panic("DMA stop for disk %d which does not exist\n", 44210037SARM gem5 Developers disk); 44310037SARM gem5 Developers 44410037SARM gem5 Developers // inform the disk of the DMA transfer abort 4457362Sgblack@eecs.umich.edu disks[disk]->abortDma(); 44610037SARM gem5 Developers } else { 44712176Sandreas.sandberg@arm.com // starting DMA transfer 44810037SARM gem5 Developers DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 44912176Sandreas.sandberg@arm.com 45012176Sandreas.sandberg@arm.com // set the BMIDEA bit 4517362Sgblack@eecs.umich.edu bmi_regs[offset + 0x2] |= BMIDEA; 4527362Sgblack@eecs.umich.edu 4537362Sgblack@eecs.umich.edu if (disks[disk] == NULL) 4547362Sgblack@eecs.umich.edu panic("DMA start for disk %d which does not exist\n", 4557362Sgblack@eecs.umich.edu disk); 45610037SARM gem5 Developers 45710037SARM gem5 Developers // inform the disk of the DMA transfer start 45810037SARM gem5 Developers if (primary) 45910037SARM gem5 Developers disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP0]); 46010037SARM gem5 Developers else 46110037SARM gem5 Developers disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP1]); 46210037SARM gem5 Developers } 4637362Sgblack@eecs.umich.edu } 46410037SARM gem5 Developers 46510037SARM gem5 Developers // update the register value 46610037SARM gem5 Developers bmi_regs[offset] = newVal; 46710037SARM gem5 Developers break; 46810037SARM gem5 Developers 46910037SARM gem5 Developers // Bus master IDE status register 47010037SARM gem5 Developers case BMIS0: 47110037SARM gem5 Developers case BMIS1: 47210037SARM gem5 Developers if (req->size != sizeof(uint8_t)) 4737362Sgblack@eecs.umich.edu panic("Invalid BMIS write size: %x\n", req->size); 47410037SARM gem5 Developers 47512176Sandreas.sandberg@arm.com oldVal = bmi_regs[offset]; 47610037SARM gem5 Developers newVal = *data; 47712176Sandreas.sandberg@arm.com 47812176Sandreas.sandberg@arm.com // the BMIDEA bit is RO 47912176Sandreas.sandberg@arm.com newVal |= (oldVal & BMIDEA); 48012176Sandreas.sandberg@arm.com 4817362Sgblack@eecs.umich.edu // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 4827362Sgblack@eecs.umich.edu if ((oldVal & IDEINTS) && (newVal & IDEINTS)) 48310037SARM gem5 Developers newVal &= ~IDEINTS; // clear the interrupt? 48410037SARM gem5 Developers else 48510037SARM gem5 Developers (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS; 48610037SARM gem5 Developers 48710037SARM gem5 Developers if ((oldVal & IDEDMAE) && (newVal & IDEDMAE)) 48810037SARM gem5 Developers newVal &= ~IDEDMAE; 48910037SARM gem5 Developers else 49010037SARM gem5 Developers (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; 49110037SARM gem5 Developers 49210037SARM gem5 Developers bmi_regs[offset] = newVal; 49310037SARM gem5 Developers break; 49410037SARM gem5 Developers 49512176Sandreas.sandberg@arm.com // Bus master IDE descriptor table pointer register 49610037SARM gem5 Developers case BMIDTP0: 49710037SARM gem5 Developers case BMIDTP1: 49810037SARM gem5 Developers if (req->size != sizeof(uint32_t)) 49910037SARM gem5 Developers panic("Invalid BMIDTP write size: %x\n", req->size); 50010037SARM gem5 Developers 50112176Sandreas.sandberg@arm.com *(uint32_t *)&bmi_regs[offset] = *(uint32_t *)data & ~0x3; 50212176Sandreas.sandberg@arm.com break; 50312176Sandreas.sandberg@arm.com 50410037SARM gem5 Developers default: 50510037SARM gem5 Developers if (req->size != sizeof(uint8_t) && 50610037SARM gem5 Developers req->size != sizeof(uint16_t) && 50710037SARM gem5 Developers req->size != sizeof(uint32_t)) 50810037SARM gem5 Developers panic("IDE controller write of invalid write size: %x\n", 50910037SARM gem5 Developers req->size); 51010037SARM gem5 Developers 51110037SARM gem5 Developers // do a default copy of data into the registers 51210037SARM gem5 Developers memcpy((void *)&bmi_regs[offset], data, req->size); 51310037SARM gem5 Developers } 51410037SARM gem5 Developers } 51512176Sandreas.sandberg@arm.com 51612176Sandreas.sandberg@arm.com return No_Fault; 51712176Sandreas.sandberg@arm.com} 51812176Sandreas.sandberg@arm.com 51910037SARM gem5 Developers//// 52010037SARM gem5 Developers// Serialization 52110037SARM gem5 Developers//// 52210037SARM gem5 Developers 52310037SARM gem5 Developersvoid 52410037SARM gem5 DevelopersIdeController::serialize(std::ostream &os) 52510037SARM gem5 Developers{ 52610037SARM gem5 Developers} 52710037SARM gem5 Developers 52810037SARM gem5 Developersvoid 52910037SARM gem5 DevelopersIdeController::unserialize(Checkpoint *cp, const std::string §ion) 53010037SARM gem5 Developers{ 53110037SARM gem5 Developers} 53210037SARM gem5 Developers 53310037SARM gem5 Developers#ifndef DOXYGEN_SHOULD_SKIP_THIS 53410037SARM gem5 Developers 53510037SARM gem5 DevelopersBEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) 53610417Sandreas.hansson@arm.com 53712176Sandreas.sandberg@arm.com SimObjectParam<IntrControl *> intr_ctrl; 53812568Sgiacomo.travaglini@arm.com SimObjectVectorParam<IdeDisk *> disks; 53910037SARM gem5 Developers SimObjectParam<MemoryController *> mmu; 54010037SARM gem5 Developers SimObjectParam<PciConfigAll *> configspace; 54110037SARM gem5 Developers SimObjectParam<PciConfigData *> configdata; 54210037SARM gem5 Developers SimObjectParam<Tsunami *> tsunami; 54310037SARM gem5 Developers Param<uint32_t> pci_bus; 54410037SARM gem5 Developers Param<uint32_t> pci_dev; 54510037SARM gem5 Developers Param<uint32_t> pci_func; 54610037SARM gem5 Developers SimObjectParam<Bus *> host_bus; 54710037SARM gem5 Developers SimObjectParam<HierParams *> hier; 54810037SARM gem5 Developers 54910037SARM gem5 DevelopersEND_DECLARE_SIM_OBJECT_PARAMS(IdeController) 55010037SARM gem5 Developers 55110037SARM gem5 DevelopersBEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) 55210037SARM gem5 Developers 55310417Sandreas.hansson@arm.com INIT_PARAM(intr_ctrl, "Interrupt Controller"), 55412176Sandreas.sandberg@arm.com INIT_PARAM(disks, "IDE disks attached to this controller"), 55512176Sandreas.sandberg@arm.com INIT_PARAM(mmu, "Memory controller"), 55612176Sandreas.sandberg@arm.com INIT_PARAM(configspace, "PCI Configspace"), 55710037SARM gem5 Developers INIT_PARAM(configdata, "PCI Config data"), 5586019Shines@cs.fsu.edu INIT_PARAM(tsunami, "Tsunami chipset pointer"), 55912299Sandreas.sandberg@arm.com INIT_PARAM(pci_bus, "PCI bus ID"), 56012299Sandreas.sandberg@arm.com INIT_PARAM(pci_dev, "PCI device number"), 56112299Sandreas.sandberg@arm.com INIT_PARAM(pci_func, "PCI function code"), 56212299Sandreas.sandberg@arm.com INIT_PARAM_DFLT(host_bus, "Host bus to attach to", NULL), 56312299Sandreas.sandberg@arm.com INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) 56412299Sandreas.sandberg@arm.com 56512299Sandreas.sandberg@arm.comEND_INIT_SIM_OBJECT_PARAMS(IdeController) 56612299Sandreas.sandberg@arm.com 56712299Sandreas.sandberg@arm.comCREATE_SIM_OBJECT(IdeController) 5687652Sminkyu.jeong@arm.com{ 5698518Sgeoffrey.blake@arm.com return new IdeController(getInstanceName(), intr_ctrl, disks, mmu, 5708518Sgeoffrey.blake@arm.com configspace, configdata, tsunami, pci_bus, 5718518Sgeoffrey.blake@arm.com pci_dev, pci_func, host_bus, hier); 5728518Sgeoffrey.blake@arm.com} 57310417Sandreas.hansson@arm.com 57412176Sandreas.sandberg@arm.comREGISTER_SIM_OBJECT("IdeController", IdeController) 5758518Sgeoffrey.blake@arm.com 5768518Sgeoffrey.blake@arm.com#endif //DOXYGEN_SHOULD_SKIP_THIS 57710037SARM gem5 Developers