ide_ctrl.cc revision 5772
16019Shines@cs.fsu.edu/* 212509Schuan.zhu@arm.com * Copyright (c) 2004-2005 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 * Authors: Andrew Schultz 296019Shines@cs.fsu.edu * Ali Saidi 306019Shines@cs.fsu.edu * Miguel Serrano 316019Shines@cs.fsu.edu */ 326019Shines@cs.fsu.edu 336019Shines@cs.fsu.edu#include <string> 346019Shines@cs.fsu.edu 356019Shines@cs.fsu.edu#include "base/trace.hh" 366019Shines@cs.fsu.edu#include "cpu/intr_control.hh" 376019Shines@cs.fsu.edu#include "dev/ide_ctrl.hh" 386019Shines@cs.fsu.edu#include "dev/ide_disk.hh" 396019Shines@cs.fsu.edu#include "mem/packet.hh" 406019Shines@cs.fsu.edu#include "mem/packet_access.hh" 416735Sgblack@eecs.umich.edu#include "params/IdeController.hh" 426735Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 4310037SARM gem5 Developers 4410037SARM gem5 Developersusing namespace std; 456019Shines@cs.fsu.edu 466019Shines@cs.fsu.edu// Bus master IDE registers 476019Shines@cs.fsu.eduenum BMIRegOffset { 486019Shines@cs.fsu.edu BMICommand = 0x0, 496019Shines@cs.fsu.edu BMIStatus = 0x2, 507362Sgblack@eecs.umich.edu BMIDescTablePtr = 0x4 5110037SARM gem5 Developers}; 526735Sgblack@eecs.umich.edu 5312334Sgabeblack@google.com// PCI config space registers 546019Shines@cs.fsu.eduenum ConfRegOffset { 558782Sgblack@eecs.umich.edu PrimaryTiming = 0x40, 566019Shines@cs.fsu.edu SecondaryTiming = 0x42, 576019Shines@cs.fsu.edu DeviceTiming = 0x44, 586019Shines@cs.fsu.edu UDMAControl = 0x48, 596019Shines@cs.fsu.edu UDMATiming = 0x4A, 606019Shines@cs.fsu.edu IDEConfig = 0x54 6111294Sandreas.hansson@arm.com}; 626019Shines@cs.fsu.edu 637362Sgblack@eecs.umich.edustatic const uint16_t timeRegWithDecodeEn = 0x8000; 646019Shines@cs.fsu.edu 656019Shines@cs.fsu.eduIdeController::Channel::Channel( 6610037SARM gem5 Developers string newName, Addr _cmdSize, Addr _ctrlSize) : 6710037SARM gem5 Developers _name(newName), 6810037SARM gem5 Developers cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize), 6910037SARM gem5 Developers master(NULL), slave(NULL), selected(NULL) 7010037SARM gem5 Developers{ 7110037SARM gem5 Developers memset(&bmiRegs, 0, sizeof(bmiRegs)); 7210037SARM gem5 Developers bmiRegs.status.dmaCap0 = 1; 7310037SARM gem5 Developers bmiRegs.status.dmaCap1 = 1; 7410037SARM gem5 Developers} 7510037SARM gem5 Developers 7612402Sgiacomo.travaglini@arm.comIdeController::Channel::~Channel() 7712402Sgiacomo.travaglini@arm.com{ 786735Sgblack@eecs.umich.edu delete master; 7910037SARM gem5 Developers delete slave; 806735Sgblack@eecs.umich.edu} 816019Shines@cs.fsu.edu 8210037SARM gem5 DevelopersIdeController::IdeController(Params *p) 8310037SARM gem5 Developers : PciDev(p), primary(name() + ".primary", BARSize[0], BARSize[1]), 8410037SARM gem5 Developers secondary(name() + ".secondary", BARSize[2], BARSize[3]), 8510037SARM gem5 Developers bmiAddr(0), bmiSize(BARSize[4]), 8610037SARM gem5 Developers primaryTiming(htole(timeRegWithDecodeEn)), 877362Sgblack@eecs.umich.edu secondaryTiming(htole(timeRegWithDecodeEn)), 8810037SARM gem5 Developers deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0), 8910037SARM gem5 Developers ioEnabled(false), bmEnabled(false) 9010037SARM gem5 Developers{ 9110037SARM gem5 Developers if (params()->disks.size() > 3) 9210037SARM gem5 Developers panic("IDE controllers support a maximum of 4 devices attached!\n"); 9310037SARM gem5 Developers 9410037SARM gem5 Developers // Assign the disks to channels 9510037SARM gem5 Developers int numDisks = params()->disks.size(); 9610037SARM gem5 Developers if (numDisks > 0) 9710037SARM gem5 Developers primary.master = params()->disks[0]; 9810037SARM gem5 Developers if (numDisks > 1) 9910037SARM gem5 Developers primary.slave = params()->disks[1]; 10010037SARM gem5 Developers if (numDisks > 2) 10110037SARM gem5 Developers secondary.master = params()->disks[2]; 10210037SARM gem5 Developers if (numDisks > 3) 1037611SGene.Wu@arm.com secondary.slave = params()->disks[3]; 10410037SARM gem5 Developers 10510037SARM gem5 Developers for (int i = 0; i < params()->disks.size(); i++) { 10610037SARM gem5 Developers params()->disks[i]->setController(this); 10710037SARM gem5 Developers } 10810037SARM gem5 Developers primary.select(false); 10910037SARM gem5 Developers secondary.select(false); 11010037SARM gem5 Developers} 11110037SARM gem5 Developers 11210037SARM gem5 Developersbool 11310037SARM gem5 DevelopersIdeController::isDiskSelected(IdeDisk *diskPtr) 11410037SARM gem5 Developers{ 11510037SARM gem5 Developers return (primary.selected == diskPtr || secondary.selected == diskPtr); 11610037SARM gem5 Developers} 11710037SARM gem5 Developers 11810037SARM gem5 Developersvoid 11910037SARM gem5 DevelopersIdeController::intrPost() 12010037SARM gem5 Developers{ 12110037SARM gem5 Developers primary.bmiRegs.status.intStatus = 1; 12210037SARM gem5 Developers PciDev::intrPost(); 12310037SARM gem5 Developers} 12410037SARM gem5 Developers 12510037SARM gem5 Developersvoid 12610037SARM gem5 DevelopersIdeController::setDmaComplete(IdeDisk *disk) 12710037SARM gem5 Developers{ 12810037SARM gem5 Developers Channel *channel; 12910037SARM gem5 Developers if (disk == primary.master || disk == primary.slave) { 13010037SARM gem5 Developers channel = &primary; 13110037SARM gem5 Developers } else if (disk == secondary.master || disk == secondary.slave) { 13210037SARM gem5 Developers channel = &secondary; 13310037SARM gem5 Developers } else { 13410037SARM gem5 Developers panic("Unable to find disk based on pointer %#x\n", disk); 13510037SARM gem5 Developers } 13610037SARM gem5 Developers 13710037SARM gem5 Developers channel->bmiRegs.command.startStop = 0; 13810037SARM gem5 Developers channel->bmiRegs.status.active = 0; 13910037SARM gem5 Developers channel->bmiRegs.status.intStatus = 1; 14010037SARM gem5 Developers} 1417362Sgblack@eecs.umich.edu 1427362Sgblack@eecs.umich.eduTick 1436735Sgblack@eecs.umich.eduIdeController::readConfig(PacketPtr pkt) 1446735Sgblack@eecs.umich.edu{ 1456735Sgblack@eecs.umich.edu int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 14610037SARM gem5 Developers if (offset < PCI_DEVICE_SPECIFIC) { 1476735Sgblack@eecs.umich.edu return PciDev::readConfig(pkt); 14810037SARM gem5 Developers } 14910037SARM gem5 Developers 15010037SARM gem5 Developers pkt->allocate(); 15110037SARM gem5 Developers 15210037SARM gem5 Developers switch (pkt->getSize()) { 15310037SARM gem5 Developers case sizeof(uint8_t): 15410037SARM gem5 Developers switch (offset) { 1556735Sgblack@eecs.umich.edu case DeviceTiming: 15610037SARM gem5 Developers pkt->set<uint8_t>(deviceTiming); 1576735Sgblack@eecs.umich.edu break; 1586735Sgblack@eecs.umich.edu case UDMAControl: 15910037SARM gem5 Developers pkt->set<uint8_t>(udmaControl); 16010037SARM gem5 Developers break; 16110037SARM gem5 Developers case PrimaryTiming + 1: 16210037SARM gem5 Developers pkt->set<uint8_t>(bits(htole(primaryTiming), 15, 8)); 16310037SARM gem5 Developers break; 16410037SARM gem5 Developers case SecondaryTiming + 1: 16510037SARM gem5 Developers pkt->set<uint8_t>(bits(htole(secondaryTiming), 15, 8)); 1666735Sgblack@eecs.umich.edu break; 1676735Sgblack@eecs.umich.edu case IDEConfig: 16810037SARM gem5 Developers pkt->set<uint8_t>(bits(htole(ideConfig), 7, 0)); 16910037SARM gem5 Developers break; 17010037SARM gem5 Developers case IDEConfig + 1: 17110037SARM gem5 Developers pkt->set<uint8_t>(bits(htole(ideConfig), 15, 8)); 17210037SARM gem5 Developers break; 1736735Sgblack@eecs.umich.edu default: 1746735Sgblack@eecs.umich.edu panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", 1756735Sgblack@eecs.umich.edu offset); 17610037SARM gem5 Developers } 17710537Sandreas.hansson@arm.com DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset, 17812402Sgiacomo.travaglini@arm.com (uint32_t)pkt->get<uint8_t>()); 17910037SARM gem5 Developers break; 18010037SARM gem5 Developers case sizeof(uint16_t): 18110037SARM gem5 Developers switch (offset) { 18210037SARM gem5 Developers case PrimaryTiming: 18310037SARM gem5 Developers pkt->set<uint16_t>(primaryTiming); 18410037SARM gem5 Developers break; 18510037SARM gem5 Developers case SecondaryTiming: 18610037SARM gem5 Developers pkt->set<uint16_t>(secondaryTiming); 18710417Sandreas.hansson@arm.com break; 18812176Sandreas.sandberg@arm.com case UDMATiming: 18910417Sandreas.hansson@arm.com pkt->set<uint16_t>(udmaTiming); 19010417Sandreas.hansson@arm.com break; 19110037SARM gem5 Developers case IDEConfig: 1926735Sgblack@eecs.umich.edu pkt->set<uint16_t>(ideConfig); 19310037SARM gem5 Developers break; 19412511Schuan.zhu@arm.com default: 1956735Sgblack@eecs.umich.edu panic("Invalid PCI configuration read for size 2 offset: %#x!\n", 19610037SARM gem5 Developers offset); 19710037SARM gem5 Developers } 19810037SARM gem5 Developers DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, 19910037SARM gem5 Developers (uint32_t)pkt->get<uint16_t>()); 20010037SARM gem5 Developers break; 20110037SARM gem5 Developers case sizeof(uint32_t): 20210037SARM gem5 Developers panic("No 32bit reads implemented for this device."); 20310037SARM gem5 Developers DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, 20410037SARM gem5 Developers (uint32_t)pkt->get<uint32_t>()); 20510037SARM gem5 Developers break; 20610037SARM gem5 Developers default: 20710037SARM gem5 Developers panic("invalid access size(?) for PCI configspace!\n"); 20810037SARM gem5 Developers } 2096019Shines@cs.fsu.edu pkt->makeAtomicResponse(); 2106019Shines@cs.fsu.edu return configDelay; 2116735Sgblack@eecs.umich.edu} 2127362Sgblack@eecs.umich.edu 2136019Shines@cs.fsu.edu 2146735Sgblack@eecs.umich.eduTick 2156735Sgblack@eecs.umich.eduIdeController::writeConfig(PacketPtr pkt) 2166735Sgblack@eecs.umich.edu{ 2176019Shines@cs.fsu.edu int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 21810037SARM gem5 Developers if (offset < PCI_DEVICE_SPECIFIC) { 21910037SARM gem5 Developers PciDev::writeConfig(pkt); 22012176Sandreas.sandberg@arm.com } else { 22112176Sandreas.sandberg@arm.com switch (pkt->getSize()) { 22212176Sandreas.sandberg@arm.com case sizeof(uint8_t): 22310037SARM gem5 Developers switch (offset) { 22412511Schuan.zhu@arm.com case DeviceTiming: 22510037SARM gem5 Developers deviceTiming = pkt->get<uint8_t>(); 22612176Sandreas.sandberg@arm.com break; 22712176Sandreas.sandberg@arm.com case UDMAControl: 22812176Sandreas.sandberg@arm.com udmaControl = pkt->get<uint8_t>(); 22912176Sandreas.sandberg@arm.com break; 23012176Sandreas.sandberg@arm.com case IDEConfig: 23112176Sandreas.sandberg@arm.com replaceBits(ideConfig, 7, 0, pkt->get<uint8_t>()); 23212176Sandreas.sandberg@arm.com break; 23312176Sandreas.sandberg@arm.com case IDEConfig + 1: 23412176Sandreas.sandberg@arm.com replaceBits(ideConfig, 15, 8, pkt->get<uint8_t>()); 23512176Sandreas.sandberg@arm.com break; 23612176Sandreas.sandberg@arm.com default: 23712176Sandreas.sandberg@arm.com panic("Invalid PCI configuration write " 23812176Sandreas.sandberg@arm.com "for size 1 offset: %#x!\n", offset); 23912176Sandreas.sandberg@arm.com } 24012176Sandreas.sandberg@arm.com DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", 24112176Sandreas.sandberg@arm.com offset, (uint32_t)pkt->get<uint8_t>()); 24212176Sandreas.sandberg@arm.com break; 24312176Sandreas.sandberg@arm.com case sizeof(uint16_t): 2446019Shines@cs.fsu.edu switch (offset) { 2456019Shines@cs.fsu.edu case PrimaryTiming: 2467400SAli.Saidi@ARM.com primaryTiming = pkt->get<uint16_t>(); 2477400SAli.Saidi@ARM.com break; 2487400SAli.Saidi@ARM.com case SecondaryTiming: 24910417Sandreas.hansson@arm.com secondaryTiming = pkt->get<uint16_t>(); 25012176Sandreas.sandberg@arm.com break; 2517400SAli.Saidi@ARM.com case UDMATiming: 2527189Sgblack@eecs.umich.edu udmaTiming = pkt->get<uint16_t>(); 2537362Sgblack@eecs.umich.edu break; 2547189Sgblack@eecs.umich.edu case IDEConfig: 2557189Sgblack@eecs.umich.edu ideConfig = pkt->get<uint16_t>(); 2567189Sgblack@eecs.umich.edu break; 2577640Sgblack@eecs.umich.edu default: 25810037SARM gem5 Developers panic("Invalid PCI configuration write " 25910205SAli.Saidi@ARM.com "for size 2 offset: %#x!\n", 2607189Sgblack@eecs.umich.edu offset); 2617189Sgblack@eecs.umich.edu } 2627189Sgblack@eecs.umich.edu DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", 2637189Sgblack@eecs.umich.edu offset, (uint32_t)pkt->get<uint16_t>()); 2647640Sgblack@eecs.umich.edu break; 2657640Sgblack@eecs.umich.edu case sizeof(uint32_t): 26610037SARM gem5 Developers panic("Write of unimplemented PCI config. register: %x\n", offset); 26710205SAli.Saidi@ARM.com break; 26810205SAli.Saidi@ARM.com default: 26910037SARM gem5 Developers panic("invalid access size(?) for PCI configspace!\n"); 27010205SAli.Saidi@ARM.com } 27110205SAli.Saidi@ARM.com pkt->makeAtomicResponse(); 27210037SARM gem5 Developers } 27310205SAli.Saidi@ARM.com 27410205SAli.Saidi@ARM.com /* Trap command register writes and enable IO/BM as appropriate as well as 2758782Sgblack@eecs.umich.edu * BARs. */ 2767189Sgblack@eecs.umich.edu switch(offset) { 27710417Sandreas.hansson@arm.com case PCI0_BASE_ADDR0: 27812176Sandreas.sandberg@arm.com if (BARAddrs[0] != 0) 27912176Sandreas.sandberg@arm.com primary.cmdAddr = BARAddrs[0]; 28012176Sandreas.sandberg@arm.com break; 28112176Sandreas.sandberg@arm.com 2827189Sgblack@eecs.umich.edu case PCI0_BASE_ADDR1: 2837189Sgblack@eecs.umich.edu if (BARAddrs[1] != 0) 2847362Sgblack@eecs.umich.edu primary.ctrlAddr = BARAddrs[1]; 2857197Sgblack@eecs.umich.edu break; 2867197Sgblack@eecs.umich.edu 28710037SARM gem5 Developers case PCI0_BASE_ADDR2: 2887197Sgblack@eecs.umich.edu if (BARAddrs[2] != 0) 28910037SARM gem5 Developers secondary.cmdAddr = BARAddrs[2]; 29010037SARM gem5 Developers break; 29110037SARM gem5 Developers 29210037SARM gem5 Developers case PCI0_BASE_ADDR3: 2938782Sgblack@eecs.umich.edu if (BARAddrs[3] != 0) 2947197Sgblack@eecs.umich.edu secondary.ctrlAddr = BARAddrs[3]; 29510417Sandreas.hansson@arm.com break; 29612176Sandreas.sandberg@arm.com 29712176Sandreas.sandberg@arm.com case PCI0_BASE_ADDR4: 29812176Sandreas.sandberg@arm.com if (BARAddrs[4] != 0) 29912176Sandreas.sandberg@arm.com bmiAddr = BARAddrs[4]; 30010037SARM gem5 Developers break; 30110037SARM gem5 Developers 30210037SARM gem5 Developers case PCI_COMMAND: 30310037SARM gem5 Developers ioEnabled = (config.command & htole(PCI_CMD_IOSE)); 30410037SARM gem5 Developers bmEnabled = (config.command & htole(PCI_CMD_BME)); 30510037SARM gem5 Developers break; 30610037SARM gem5 Developers } 30710037SARM gem5 Developers return configDelay; 30810037SARM gem5 Developers} 30910417Sandreas.hansson@arm.com 31012176Sandreas.sandberg@arm.comvoid 31112176Sandreas.sandberg@arm.comIdeController::Channel::accessCommand(Addr offset, 31212176Sandreas.sandberg@arm.com int size, uint8_t *data, bool read) 31310037SARM gem5 Developers{ 31410037SARM gem5 Developers const Addr SelectOffset = 6; 31510037SARM gem5 Developers const uint8_t SelectDevBit = 0x10; 31610037SARM gem5 Developers 31710037SARM gem5 Developers if (!read && offset == SelectOffset) 31810037SARM gem5 Developers select(*data & SelectDevBit); 31910037SARM gem5 Developers 32010037SARM gem5 Developers if (selected == NULL) { 32110037SARM gem5 Developers assert(size == sizeof(uint8_t)); 32210037SARM gem5 Developers *data = 0; 32310037SARM gem5 Developers } else if (read) { 32410037SARM gem5 Developers selected->readCommand(offset, size, data); 32510037SARM gem5 Developers } else { 32610037SARM gem5 Developers selected->writeCommand(offset, size, data); 32710037SARM gem5 Developers } 32812509Schuan.zhu@arm.com} 32912509Schuan.zhu@arm.com 33012176Sandreas.sandberg@arm.comvoid 33110037SARM gem5 DevelopersIdeController::Channel::accessControl(Addr offset, 33210037SARM gem5 Developers int size, uint8_t *data, bool read) 33310037SARM gem5 Developers{ 33410037SARM gem5 Developers if (selected == NULL) { 33510037SARM gem5 Developers assert(size == sizeof(uint8_t)); 33610037SARM gem5 Developers *data = 0; 33710037SARM gem5 Developers } else if (read) { 33810037SARM gem5 Developers selected->readControl(offset, size, data); 33910037SARM gem5 Developers } else { 34010037SARM gem5 Developers selected->writeControl(offset, size, data); 34110037SARM gem5 Developers } 34210037SARM gem5 Developers} 34310037SARM gem5 Developers 34410037SARM gem5 Developersvoid 34510037SARM gem5 DevelopersIdeController::Channel::accessBMI(Addr offset, 34612176Sandreas.sandberg@arm.com int size, uint8_t *data, bool read) 34710037SARM gem5 Developers{ 34810037SARM gem5 Developers assert(offset + size <= sizeof(BMIRegs)); 34910037SARM gem5 Developers if (read) { 35010037SARM gem5 Developers memcpy(data, (uint8_t *)&bmiRegs + offset, size); 35110037SARM gem5 Developers } else { 35210037SARM gem5 Developers switch (offset) { 35311576SDylan.Johnson@ARM.com case BMICommand: 35412176Sandreas.sandberg@arm.com { 35510037SARM gem5 Developers if (size != sizeof(uint8_t)) 35610037SARM gem5 Developers panic("Invalid BMIC write size: %x\n", size); 35710037SARM gem5 Developers 35810037SARM gem5 Developers BMICommandReg oldVal = bmiRegs.command; 35910037SARM gem5 Developers BMICommandReg newVal = *data; 36010037SARM gem5 Developers 36110037SARM gem5 Developers // if a DMA transfer is in progress, R/W control cannot change 36210037SARM gem5 Developers if (oldVal.startStop && oldVal.rw != newVal.rw) 36310037SARM gem5 Developers oldVal.rw = newVal.rw; 36410037SARM gem5 Developers 36510037SARM gem5 Developers if (oldVal.startStop != newVal.startStop) { 36610037SARM gem5 Developers if (selected == NULL) 36710037SARM gem5 Developers panic("DMA start for disk which does not exist\n"); 36810037SARM gem5 Developers 36910037SARM gem5 Developers if (oldVal.startStop) { 37012176Sandreas.sandberg@arm.com DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 3717197Sgblack@eecs.umich.edu bmiRegs.status.active = 0; 3727362Sgblack@eecs.umich.edu 3737362Sgblack@eecs.umich.edu selected->abortDma(); 3747362Sgblack@eecs.umich.edu } else { 3757362Sgblack@eecs.umich.edu DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 3767362Sgblack@eecs.umich.edu bmiRegs.status.active = 1; 37710037SARM gem5 Developers 37810037SARM gem5 Developers selected->startDma(letoh(bmiRegs.bmidtp)); 37910037SARM gem5 Developers } 38010037SARM gem5 Developers } 38110037SARM gem5 Developers 38210037SARM gem5 Developers bmiRegs.command = newVal; 3837362Sgblack@eecs.umich.edu } 38410037SARM gem5 Developers break; 38510037SARM gem5 Developers case BMIStatus: 38610037SARM gem5 Developers { 38710037SARM gem5 Developers if (size != sizeof(uint8_t)) 38810037SARM gem5 Developers panic("Invalid BMIS write size: %x\n", size); 38910037SARM gem5 Developers 3907362Sgblack@eecs.umich.edu BMIStatusReg oldVal = bmiRegs.status; 39110037SARM gem5 Developers BMIStatusReg newVal = *data; 39210037SARM gem5 Developers 39310037SARM gem5 Developers // the BMIDEA bit is read only 39410037SARM gem5 Developers newVal.active = oldVal.active; 39510037SARM gem5 Developers 39610037SARM gem5 Developers // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 3977362Sgblack@eecs.umich.edu if (oldVal.intStatus && newVal.intStatus) 3987362Sgblack@eecs.umich.edu newVal.intStatus = 0; // clear the interrupt? 39910537Sandreas.hansson@arm.com else 40010537Sandreas.hansson@arm.com newVal.intStatus = oldVal.intStatus; 40110537Sandreas.hansson@arm.com if (oldVal.dmaError && newVal.dmaError) 40210537Sandreas.hansson@arm.com newVal.dmaError = 0; 40310537Sandreas.hansson@arm.com else 40410037SARM gem5 Developers newVal.dmaError = oldVal.dmaError; 4057362Sgblack@eecs.umich.edu 4067362Sgblack@eecs.umich.edu bmiRegs.status = newVal; 40710417Sandreas.hansson@arm.com } 40812176Sandreas.sandberg@arm.com break; 40910037SARM gem5 Developers case BMIDescTablePtr: 41012176Sandreas.sandberg@arm.com if (size != sizeof(uint32_t)) 41112176Sandreas.sandberg@arm.com panic("Invalid BMIDTP write size: %x\n", size); 41212176Sandreas.sandberg@arm.com bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3); 41312176Sandreas.sandberg@arm.com break; 41412176Sandreas.sandberg@arm.com default: 41510037SARM gem5 Developers if (size != sizeof(uint8_t) && size != sizeof(uint16_t) && 4167362Sgblack@eecs.umich.edu size != sizeof(uint32_t)) 4177362Sgblack@eecs.umich.edu panic("IDE controller write of invalid write size: %x\n", size); 4187362Sgblack@eecs.umich.edu memcpy((uint8_t *)&bmiRegs + offset, data, size); 4197362Sgblack@eecs.umich.edu } 4207362Sgblack@eecs.umich.edu } 42110037SARM gem5 Developers} 42210037SARM gem5 Developers 42310037SARM gem5 Developersvoid 4247362Sgblack@eecs.umich.eduIdeController::dispatchAccess(PacketPtr pkt, bool read) 42510037SARM gem5 Developers{ 42610037SARM gem5 Developers pkt->allocate(); 42710037SARM gem5 Developers if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) 42810037SARM gem5 Developers panic("Bad IDE read size: %d\n", pkt->getSize()); 4297362Sgblack@eecs.umich.edu 43010037SARM gem5 Developers if (!ioEnabled) { 43112176Sandreas.sandberg@arm.com pkt->makeAtomicResponse(); 43210037SARM gem5 Developers DPRINTF(IdeCtrl, "io not enabled\n"); 43312176Sandreas.sandberg@arm.com return; 43412176Sandreas.sandberg@arm.com } 4357362Sgblack@eecs.umich.edu 4367362Sgblack@eecs.umich.edu Addr addr = pkt->getAddr(); 4377362Sgblack@eecs.umich.edu int size = pkt->getSize(); 4387362Sgblack@eecs.umich.edu uint8_t *dataPtr = pkt->getPtr<uint8_t>(); 4397362Sgblack@eecs.umich.edu 44010037SARM gem5 Developers if (addr >= primary.cmdAddr && 44110037SARM gem5 Developers addr < (primary.cmdAddr + primary.cmdSize)) { 44210037SARM gem5 Developers addr -= primary.cmdAddr; 44310037SARM gem5 Developers primary.accessCommand(addr, size, dataPtr, read); 44410037SARM gem5 Developers } else if (addr >= primary.ctrlAddr && 44510037SARM gem5 Developers addr < (primary.ctrlAddr + primary.ctrlSize)) { 44610037SARM gem5 Developers addr -= primary.ctrlAddr; 4477362Sgblack@eecs.umich.edu primary.accessControl(addr, size, dataPtr, read); 44810037SARM gem5 Developers } else if (addr >= secondary.cmdAddr && 44910037SARM gem5 Developers addr < (secondary.cmdAddr + secondary.cmdSize)) { 45010037SARM gem5 Developers addr -= secondary.cmdAddr; 45110037SARM gem5 Developers secondary.accessCommand(addr, size, dataPtr, read); 45210037SARM gem5 Developers } else if (addr >= secondary.ctrlAddr && 45310037SARM gem5 Developers addr < (secondary.ctrlAddr + secondary.ctrlSize)) { 45410037SARM gem5 Developers addr -= secondary.ctrlAddr; 45510037SARM gem5 Developers secondary.accessControl(addr, size, dataPtr, read); 45610037SARM gem5 Developers } else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) { 4577362Sgblack@eecs.umich.edu if (!read && !bmEnabled) 45810037SARM gem5 Developers return; 45912176Sandreas.sandberg@arm.com addr -= bmiAddr; 46010037SARM gem5 Developers if (addr < sizeof(Channel::BMIRegs)) { 46112176Sandreas.sandberg@arm.com primary.accessBMI(addr, size, dataPtr, read); 46212176Sandreas.sandberg@arm.com } else { 46312176Sandreas.sandberg@arm.com addr -= sizeof(Channel::BMIRegs); 46412176Sandreas.sandberg@arm.com secondary.accessBMI(addr, size, dataPtr, read); 4657362Sgblack@eecs.umich.edu } 4667362Sgblack@eecs.umich.edu } else { 46710037SARM gem5 Developers panic("IDE controller access to invalid address: %#x\n", addr); 46810037SARM gem5 Developers } 46910037SARM gem5 Developers 47010037SARM gem5 Developers uint32_t data; 47110037SARM gem5 Developers if (pkt->getSize() == 1) 47210037SARM gem5 Developers data = pkt->get<uint8_t>(); 47310037SARM gem5 Developers else if (pkt->getSize() == 2) 47410037SARM gem5 Developers data = pkt->get<uint16_t>(); 47510037SARM gem5 Developers else 47610037SARM gem5 Developers data = pkt->get<uint32_t>(); 47710037SARM gem5 Developers DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n", 47810037SARM gem5 Developers read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data); 47912176Sandreas.sandberg@arm.com 48010037SARM gem5 Developers pkt->makeAtomicResponse(); 48110037SARM gem5 Developers} 48210037SARM gem5 Developers 48310037SARM gem5 DevelopersTick 48410037SARM gem5 DevelopersIdeController::read(PacketPtr pkt) 48512176Sandreas.sandberg@arm.com{ 48612176Sandreas.sandberg@arm.com dispatchAccess(pkt, true); 48712176Sandreas.sandberg@arm.com return pioDelay; 48810037SARM gem5 Developers} 48910037SARM gem5 Developers 49010037SARM gem5 DevelopersTick 49110037SARM gem5 DevelopersIdeController::write(PacketPtr pkt) 49210037SARM gem5 Developers{ 49310037SARM gem5 Developers dispatchAccess(pkt, false); 49410037SARM gem5 Developers return pioDelay; 49510037SARM gem5 Developers} 49610037SARM gem5 Developers 49710037SARM gem5 Developersvoid 49810037SARM gem5 DevelopersIdeController::serialize(std::ostream &os) 49912176Sandreas.sandberg@arm.com{ 50012176Sandreas.sandberg@arm.com // Serialize the PciDev base class 50112176Sandreas.sandberg@arm.com PciDev::serialize(os); 50212176Sandreas.sandberg@arm.com 50310037SARM gem5 Developers // Serialize channels 50410037SARM gem5 Developers primary.serialize(os); 50510037SARM gem5 Developers secondary.serialize(os); 50610037SARM gem5 Developers 50710037SARM gem5 Developers // Serialize config registers 50810037SARM gem5 Developers SERIALIZE_SCALAR(primaryTiming); 50910037SARM gem5 Developers SERIALIZE_SCALAR(secondaryTiming); 51010037SARM gem5 Developers SERIALIZE_SCALAR(deviceTiming); 51110037SARM gem5 Developers SERIALIZE_SCALAR(udmaControl); 51210037SARM gem5 Developers SERIALIZE_SCALAR(udmaTiming); 51310037SARM gem5 Developers SERIALIZE_SCALAR(ideConfig); 51410037SARM gem5 Developers 51510037SARM gem5 Developers // Serialize internal state 51610037SARM gem5 Developers SERIALIZE_SCALAR(ioEnabled); 51710037SARM gem5 Developers SERIALIZE_SCALAR(bmEnabled); 51810037SARM gem5 Developers} 51910037SARM gem5 Developers 52010417Sandreas.hansson@arm.comvoid 52112176Sandreas.sandberg@arm.comIdeController::Channel::serialize(std::ostream &os) 52210037SARM gem5 Developers{ 52310037SARM gem5 Developers SERIALIZE_SCALAR(cmdAddr); 52410037SARM gem5 Developers SERIALIZE_SCALAR(cmdSize); 52510037SARM gem5 Developers SERIALIZE_SCALAR(ctrlAddr); 52610037SARM gem5 Developers SERIALIZE_SCALAR(ctrlSize); 52710037SARM gem5 Developers SERIALIZE_SCALAR((uint8_t)bmiRegs.command); 52810037SARM gem5 Developers SERIALIZE_SCALAR(bmiRegs.reserved0); 52910037SARM gem5 Developers SERIALIZE_SCALAR((uint8_t)bmiRegs.status); 53010037SARM gem5 Developers SERIALIZE_SCALAR(bmiRegs.reserved1); 53110037SARM gem5 Developers SERIALIZE_SCALAR(bmiRegs.bmidtp); 53210037SARM gem5 Developers SERIALIZE_SCALAR(selectBit); 53310037SARM gem5 Developers} 53410037SARM gem5 Developers 53510037SARM gem5 Developersvoid 53610417Sandreas.hansson@arm.comIdeController::unserialize(Checkpoint *cp, const std::string §ion) 53712176Sandreas.sandberg@arm.com{ 53812176Sandreas.sandberg@arm.com // Unserialize the PciDev base class 53912176Sandreas.sandberg@arm.com PciDev::unserialize(cp, section); 54010037SARM gem5 Developers 5416019Shines@cs.fsu.edu // Unserialize channels 54212299Sandreas.sandberg@arm.com primary.unserialize(cp, section); 54312299Sandreas.sandberg@arm.com secondary.unserialize(cp, section); 54412299Sandreas.sandberg@arm.com 54512299Sandreas.sandberg@arm.com // Unserialize config registers 54612299Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(primaryTiming); 54712299Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(secondaryTiming); 54812299Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(deviceTiming); 54912299Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(udmaControl); 55012299Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(udmaTiming); 5517652Sminkyu.jeong@arm.com UNSERIALIZE_SCALAR(ideConfig); 5528518Sgeoffrey.blake@arm.com 5538518Sgeoffrey.blake@arm.com // Unserialize internal state 5548518Sgeoffrey.blake@arm.com UNSERIALIZE_SCALAR(ioEnabled); 5558518Sgeoffrey.blake@arm.com UNSERIALIZE_SCALAR(bmEnabled); 55610417Sandreas.hansson@arm.com} 55712176Sandreas.sandberg@arm.com 5588518Sgeoffrey.blake@arm.comvoid 5598518Sgeoffrey.blake@arm.comIdeController::Channel::unserialize( 56010037SARM gem5 Developers Checkpoint *cp, const std::string §ion) 56110037SARM gem5 Developers{ 56210037SARM gem5 Developers uint8_t temp; 56310037SARM gem5 Developers UNSERIALIZE_SCALAR(cmdAddr); 56410037SARM gem5 Developers UNSERIALIZE_SCALAR(cmdSize); 56510037SARM gem5 Developers UNSERIALIZE_SCALAR(ctrlAddr); 56610037SARM gem5 Developers UNSERIALIZE_SCALAR(ctrlSize); 56711929SMatteo.Andreozzi@arm.com UNSERIALIZE_SCALAR(temp); 56812032Sandreas.sandberg@arm.com bmiRegs.command = temp; 56912032Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(bmiRegs.reserved0); 57011929SMatteo.Andreozzi@arm.com UNSERIALIZE_SCALAR(temp); 57111929SMatteo.Andreozzi@arm.com bmiRegs.status = temp; 57211929SMatteo.Andreozzi@arm.com UNSERIALIZE_SCALAR(bmiRegs.reserved1); 57311929SMatteo.Andreozzi@arm.com UNSERIALIZE_SCALAR(bmiRegs.bmidtp); 57411929SMatteo.Andreozzi@arm.com UNSERIALIZE_SCALAR(selectBit); 57511929SMatteo.Andreozzi@arm.com select(selectBit); 57611929SMatteo.Andreozzi@arm.com} 57711929SMatteo.Andreozzi@arm.com 57811929SMatteo.Andreozzi@arm.comIdeController * 57911929SMatteo.Andreozzi@arm.comIdeControllerParams::create() 58011929SMatteo.Andreozzi@arm.com{ 58111929SMatteo.Andreozzi@arm.com return new IdeController(this); 58211929SMatteo.Andreozzi@arm.com} 58311929SMatteo.Andreozzi@arm.com