ide_ctrl.cc revision 2846
110259SAndrew.Bardsley@arm.com/* 210259SAndrew.Bardsley@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 310259SAndrew.Bardsley@arm.com * All rights reserved. 410259SAndrew.Bardsley@arm.com * 510259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without 610259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are 710259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright 810259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer; 910259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright 1010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the 1110259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution; 1210259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its 1310259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from 1410259SAndrew.Bardsley@arm.com * this software without specific prior written permission. 1510259SAndrew.Bardsley@arm.com * 1610259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710259SAndrew.Bardsley@arm.com * 2810259SAndrew.Bardsley@arm.com * Authors: Andrew Schultz 2910259SAndrew.Bardsley@arm.com * Ali Saidi 3010259SAndrew.Bardsley@arm.com * Miguel Serrano 3110259SAndrew.Bardsley@arm.com */ 3210259SAndrew.Bardsley@arm.com 3310259SAndrew.Bardsley@arm.com#include <cstddef> 3410259SAndrew.Bardsley@arm.com#include <cstdlib> 3510259SAndrew.Bardsley@arm.com#include <string> 3610259SAndrew.Bardsley@arm.com#include <vector> 3710259SAndrew.Bardsley@arm.com 3810259SAndrew.Bardsley@arm.com#include "base/trace.hh" 3910259SAndrew.Bardsley@arm.com#include "cpu/intr_control.hh" 4011793Sbrandon.potter@amd.com#include "dev/ide_ctrl.hh" 4111793Sbrandon.potter@amd.com#include "dev/ide_disk.hh" 4210259SAndrew.Bardsley@arm.com#include "dev/pciconfigall.hh" 4310259SAndrew.Bardsley@arm.com#include "dev/pcireg.h" 4410259SAndrew.Bardsley@arm.com#include "dev/platform.hh" 4510259SAndrew.Bardsley@arm.com#include "mem/packet.hh" 4610259SAndrew.Bardsley@arm.com#include "sim/builder.hh" 4710259SAndrew.Bardsley@arm.com#include "sim/sim_object.hh" 4810259SAndrew.Bardsley@arm.com#include "sim/byteswap.hh" 4910259SAndrew.Bardsley@arm.com 5010259SAndrew.Bardsley@arm.comusing namespace std; 5110259SAndrew.Bardsley@arm.com 5210259SAndrew.Bardsley@arm.com//// 5310259SAndrew.Bardsley@arm.com// Initialization and destruction 5410259SAndrew.Bardsley@arm.com//// 5510259SAndrew.Bardsley@arm.com 5610259SAndrew.Bardsley@arm.comIdeController::IdeController(Params *p) 5710259SAndrew.Bardsley@arm.com : PciDev(p) 5810259SAndrew.Bardsley@arm.com{ 5910259SAndrew.Bardsley@arm.com // initialize the PIO interface addresses 6010259SAndrew.Bardsley@arm.com pri_cmd_addr = 0; 6110259SAndrew.Bardsley@arm.com pri_cmd_size = BARSize[0]; 6210259SAndrew.Bardsley@arm.com 6310259SAndrew.Bardsley@arm.com pri_ctrl_addr = 0; 6410259SAndrew.Bardsley@arm.com pri_ctrl_size = BARSize[1]; 6510259SAndrew.Bardsley@arm.com 6610259SAndrew.Bardsley@arm.com sec_cmd_addr = 0; 6710259SAndrew.Bardsley@arm.com sec_cmd_size = BARSize[2]; 6810259SAndrew.Bardsley@arm.com 6910259SAndrew.Bardsley@arm.com sec_ctrl_addr = 0; 7010259SAndrew.Bardsley@arm.com sec_ctrl_size = BARSize[3]; 7110259SAndrew.Bardsley@arm.com 7210259SAndrew.Bardsley@arm.com // initialize the bus master interface (BMI) address to be configured 7310259SAndrew.Bardsley@arm.com // via PCI 7410259SAndrew.Bardsley@arm.com bmi_addr = 0; 7510259SAndrew.Bardsley@arm.com bmi_size = BARSize[4]; 7610259SAndrew.Bardsley@arm.com 7710259SAndrew.Bardsley@arm.com // zero out all of the registers 7810259SAndrew.Bardsley@arm.com memset(bmi_regs.data, 0, sizeof(bmi_regs)); 7910259SAndrew.Bardsley@arm.com memset(config_regs.data, 0, sizeof(config_regs.data)); 8010259SAndrew.Bardsley@arm.com 8110259SAndrew.Bardsley@arm.com // setup initial values 8210259SAndrew.Bardsley@arm.com // enable both channels 8310259SAndrew.Bardsley@arm.com config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN); 8410259SAndrew.Bardsley@arm.com config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN); 8510259SAndrew.Bardsley@arm.com bmi_regs.bmis0 = DMA1CAP | DMA0CAP; 8610259SAndrew.Bardsley@arm.com bmi_regs.bmis1 = DMA1CAP | DMA0CAP; 8710259SAndrew.Bardsley@arm.com 8810259SAndrew.Bardsley@arm.com // reset all internal variables 8910259SAndrew.Bardsley@arm.com io_enabled = false; 9010259SAndrew.Bardsley@arm.com bm_enabled = false; 9110259SAndrew.Bardsley@arm.com memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); 9210259SAndrew.Bardsley@arm.com 9310259SAndrew.Bardsley@arm.com // setup the disks attached to controller 9410259SAndrew.Bardsley@arm.com memset(disks, 0, sizeof(disks)); 9510259SAndrew.Bardsley@arm.com dev[0] = 0; 9610259SAndrew.Bardsley@arm.com dev[1] = 0; 9710259SAndrew.Bardsley@arm.com 9810259SAndrew.Bardsley@arm.com if (params()->disks.size() > 3) 9910259SAndrew.Bardsley@arm.com panic("IDE controllers support a maximum of 4 devices attached!\n"); 10010259SAndrew.Bardsley@arm.com 10110259SAndrew.Bardsley@arm.com for (int i = 0; i < params()->disks.size(); i++) { 10210259SAndrew.Bardsley@arm.com disks[i] = params()->disks[i]; 10310259SAndrew.Bardsley@arm.com disks[i]->setController(this); 10410259SAndrew.Bardsley@arm.com } 10510259SAndrew.Bardsley@arm.com} 10610259SAndrew.Bardsley@arm.com 10710259SAndrew.Bardsley@arm.comIdeController::~IdeController() 10810259SAndrew.Bardsley@arm.com{ 10910259SAndrew.Bardsley@arm.com for (int i = 0; i < 4; i++) 11010259SAndrew.Bardsley@arm.com if (disks[i]) 11110259SAndrew.Bardsley@arm.com delete disks[i]; 11210259SAndrew.Bardsley@arm.com} 11310259SAndrew.Bardsley@arm.com 11410259SAndrew.Bardsley@arm.com//// 11510259SAndrew.Bardsley@arm.com// Utility functions 11610259SAndrew.Bardsley@arm.com/// 11710259SAndrew.Bardsley@arm.com 11810259SAndrew.Bardsley@arm.comvoid 11910259SAndrew.Bardsley@arm.comIdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, 12010259SAndrew.Bardsley@arm.com IdeRegType ®_type) 12110259SAndrew.Bardsley@arm.com{ 12210259SAndrew.Bardsley@arm.com offset = addr; 12310259SAndrew.Bardsley@arm.com 12410259SAndrew.Bardsley@arm.com if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) { 12510259SAndrew.Bardsley@arm.com offset -= pri_cmd_addr; 12610259SAndrew.Bardsley@arm.com reg_type = COMMAND_BLOCK; 12710259SAndrew.Bardsley@arm.com channel = PRIMARY; 12810259SAndrew.Bardsley@arm.com } else if (addr >= pri_ctrl_addr && 12910259SAndrew.Bardsley@arm.com addr < (pri_ctrl_addr + pri_ctrl_size)) { 13010259SAndrew.Bardsley@arm.com offset -= pri_ctrl_addr; 13110259SAndrew.Bardsley@arm.com reg_type = CONTROL_BLOCK; 13210259SAndrew.Bardsley@arm.com channel = PRIMARY; 13310259SAndrew.Bardsley@arm.com } else if (addr >= sec_cmd_addr && 13410259SAndrew.Bardsley@arm.com addr < (sec_cmd_addr + sec_cmd_size)) { 13510259SAndrew.Bardsley@arm.com offset -= sec_cmd_addr; 13610259SAndrew.Bardsley@arm.com reg_type = COMMAND_BLOCK; 13710259SAndrew.Bardsley@arm.com channel = SECONDARY; 13810259SAndrew.Bardsley@arm.com } else if (addr >= sec_ctrl_addr && 13910259SAndrew.Bardsley@arm.com addr < (sec_ctrl_addr + sec_ctrl_size)) { 14010259SAndrew.Bardsley@arm.com offset -= sec_ctrl_addr; 14110259SAndrew.Bardsley@arm.com reg_type = CONTROL_BLOCK; 14210259SAndrew.Bardsley@arm.com channel = SECONDARY; 14310259SAndrew.Bardsley@arm.com } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) { 14410259SAndrew.Bardsley@arm.com offset -= bmi_addr; 14510259SAndrew.Bardsley@arm.com reg_type = BMI_BLOCK; 14610259SAndrew.Bardsley@arm.com channel = (offset < BMIC1) ? PRIMARY : SECONDARY; 14710259SAndrew.Bardsley@arm.com } else { 14810259SAndrew.Bardsley@arm.com panic("IDE controller access to invalid address: %#x\n", addr); 14910259SAndrew.Bardsley@arm.com } 15010259SAndrew.Bardsley@arm.com} 15110259SAndrew.Bardsley@arm.com 15210259SAndrew.Bardsley@arm.comint 15310259SAndrew.Bardsley@arm.comIdeController::getDisk(IdeChannel channel) 15410259SAndrew.Bardsley@arm.com{ 15510259SAndrew.Bardsley@arm.com int disk = 0; 15610259SAndrew.Bardsley@arm.com uint8_t *devBit = &dev[0]; 15710259SAndrew.Bardsley@arm.com 15810259SAndrew.Bardsley@arm.com if (channel == SECONDARY) { 15910259SAndrew.Bardsley@arm.com disk += 2; 16010259SAndrew.Bardsley@arm.com devBit = &dev[1]; 16110259SAndrew.Bardsley@arm.com } 16210259SAndrew.Bardsley@arm.com 16310259SAndrew.Bardsley@arm.com disk += *devBit; 16410259SAndrew.Bardsley@arm.com 16510259SAndrew.Bardsley@arm.com assert(*devBit == 0 || *devBit == 1); 16610259SAndrew.Bardsley@arm.com 16710259SAndrew.Bardsley@arm.com return disk; 16810259SAndrew.Bardsley@arm.com} 16910259SAndrew.Bardsley@arm.com 17010259SAndrew.Bardsley@arm.comint 17110259SAndrew.Bardsley@arm.comIdeController::getDisk(IdeDisk *diskPtr) 17210259SAndrew.Bardsley@arm.com{ 17310259SAndrew.Bardsley@arm.com for (int i = 0; i < 4; i++) { 17410259SAndrew.Bardsley@arm.com if ((long)diskPtr == (long)disks[i]) 17510259SAndrew.Bardsley@arm.com return i; 17610259SAndrew.Bardsley@arm.com } 17710259SAndrew.Bardsley@arm.com return -1; 17810259SAndrew.Bardsley@arm.com} 17910259SAndrew.Bardsley@arm.com 18010259SAndrew.Bardsley@arm.combool 18110259SAndrew.Bardsley@arm.comIdeController::isDiskSelected(IdeDisk *diskPtr) 18210259SAndrew.Bardsley@arm.com{ 18310259SAndrew.Bardsley@arm.com for (int i = 0; i < 4; i++) { 18410259SAndrew.Bardsley@arm.com if ((long)diskPtr == (long)disks[i]) { 18510259SAndrew.Bardsley@arm.com // is disk is on primary or secondary channel 18610259SAndrew.Bardsley@arm.com int channel = i/2; 18710259SAndrew.Bardsley@arm.com // is disk the master or slave 18810259SAndrew.Bardsley@arm.com int devID = i%2; 18910259SAndrew.Bardsley@arm.com 19010259SAndrew.Bardsley@arm.com return (dev[channel] == devID); 19110259SAndrew.Bardsley@arm.com } 19210259SAndrew.Bardsley@arm.com } 19310259SAndrew.Bardsley@arm.com panic("Unable to find disk by pointer!!\n"); 19410259SAndrew.Bardsley@arm.com} 19510259SAndrew.Bardsley@arm.com 19610259SAndrew.Bardsley@arm.com//// 19710259SAndrew.Bardsley@arm.com// Command completion 19810259SAndrew.Bardsley@arm.com//// 19910259SAndrew.Bardsley@arm.com 20010259SAndrew.Bardsley@arm.comvoid 20110259SAndrew.Bardsley@arm.comIdeController::setDmaComplete(IdeDisk *disk) 20210259SAndrew.Bardsley@arm.com{ 20310259SAndrew.Bardsley@arm.com int diskNum = getDisk(disk); 20410259SAndrew.Bardsley@arm.com 20510259SAndrew.Bardsley@arm.com if (diskNum < 0) 20610259SAndrew.Bardsley@arm.com panic("Unable to find disk based on pointer %#x\n", disk); 20710259SAndrew.Bardsley@arm.com 20810259SAndrew.Bardsley@arm.com if (diskNum < 2) { 20910259SAndrew.Bardsley@arm.com // clear the start/stop bit in the command register 21010259SAndrew.Bardsley@arm.com bmi_regs.bmic0 &= ~SSBM; 21110259SAndrew.Bardsley@arm.com // clear the bus master active bit in the status register 21210259SAndrew.Bardsley@arm.com bmi_regs.bmis0 &= ~BMIDEA; 21310259SAndrew.Bardsley@arm.com // set the interrupt bit 21410259SAndrew.Bardsley@arm.com bmi_regs.bmis0 |= IDEINTS; 21510259SAndrew.Bardsley@arm.com } else { 21610259SAndrew.Bardsley@arm.com // clear the start/stop bit in the command register 21710259SAndrew.Bardsley@arm.com bmi_regs.bmic1 &= ~SSBM; 21810259SAndrew.Bardsley@arm.com // clear the bus master active bit in the status register 21910259SAndrew.Bardsley@arm.com bmi_regs.bmis1 &= ~BMIDEA; 22011567Smitch.hayenga@arm.com // set the interrupt bit 22111567Smitch.hayenga@arm.com bmi_regs.bmis1 |= IDEINTS; 22210259SAndrew.Bardsley@arm.com } 22310259SAndrew.Bardsley@arm.com} 22410259SAndrew.Bardsley@arm.com 22510259SAndrew.Bardsley@arm.com 22610259SAndrew.Bardsley@arm.com//// 22711567Smitch.hayenga@arm.com// Read and write handling 22810259SAndrew.Bardsley@arm.com//// 22910259SAndrew.Bardsley@arm.com 23010259SAndrew.Bardsley@arm.comTick 23110379Sandreas.hansson@arm.comIdeController::readConfig(Packet *pkt) 23210379Sandreas.hansson@arm.com{ 23310259SAndrew.Bardsley@arm.com int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 23410259SAndrew.Bardsley@arm.com if (offset < PCI_DEVICE_SPECIFIC) 23510259SAndrew.Bardsley@arm.com return PciDev::readConfig(pkt); 23610259SAndrew.Bardsley@arm.com assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END); 23710259SAndrew.Bardsley@arm.com 23810259SAndrew.Bardsley@arm.com pkt->allocate(); 23910259SAndrew.Bardsley@arm.com 24010259SAndrew.Bardsley@arm.com switch (pkt->getSize()) { 24110259SAndrew.Bardsley@arm.com case sizeof(uint8_t): 24210259SAndrew.Bardsley@arm.com switch (offset) { 24310259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_DEV_TIMING: 24410259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(config_regs.sidetim); 24510259SAndrew.Bardsley@arm.com break; 24610259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_UDMA_CNTRL: 24710259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(config_regs.udmactl); 24810259SAndrew.Bardsley@arm.com break; 24910259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_PRIM_TIMING+1: 25010259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(htole(config_regs.idetim0) >> 8); 25110259SAndrew.Bardsley@arm.com break; 25210259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_SEC_TIMING+1: 25310259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(htole(config_regs.idetim1) >> 8); 25410259SAndrew.Bardsley@arm.com break; 25510259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_IDE_CONFIG: 25610259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(htole(config_regs.ideconfig) & 0xFF); 25710259SAndrew.Bardsley@arm.com break; 25810259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_IDE_CONFIG+1: 25910259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(htole(config_regs.ideconfig) >> 8); 26010259SAndrew.Bardsley@arm.com break; 26110259SAndrew.Bardsley@arm.com default: 26210259SAndrew.Bardsley@arm.com panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", 26310259SAndrew.Bardsley@arm.com offset); 26410259SAndrew.Bardsley@arm.com } 26510259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset, 26610259SAndrew.Bardsley@arm.com (uint32_t)pkt->get<uint8_t>()); 26710259SAndrew.Bardsley@arm.com break; 26810259SAndrew.Bardsley@arm.com case sizeof(uint16_t): 26910259SAndrew.Bardsley@arm.com switch (offset) { 27010259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_PRIM_TIMING: 27110259SAndrew.Bardsley@arm.com pkt->set<uint16_t>(config_regs.idetim0); 27210259SAndrew.Bardsley@arm.com break; 27310259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_SEC_TIMING: 27410259SAndrew.Bardsley@arm.com pkt->set<uint16_t>(config_regs.idetim1); 27510259SAndrew.Bardsley@arm.com break; 27610259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_UDMA_TIMING: 27710259SAndrew.Bardsley@arm.com pkt->set<uint16_t>(config_regs.udmatim); 27810379Sandreas.hansson@arm.com break; 27910379Sandreas.hansson@arm.com case IDE_CTRL_CONF_IDE_CONFIG: 28010259SAndrew.Bardsley@arm.com pkt->set<uint16_t>(config_regs.ideconfig); 28110259SAndrew.Bardsley@arm.com break; 28210259SAndrew.Bardsley@arm.com default: 28310259SAndrew.Bardsley@arm.com panic("Invalid PCI configuration read for size 2 offset: %#x!\n", 28410259SAndrew.Bardsley@arm.com offset); 28510259SAndrew.Bardsley@arm.com } 28610259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, 28710259SAndrew.Bardsley@arm.com (uint32_t)pkt->get<uint16_t>()); 28810259SAndrew.Bardsley@arm.com break; 28910259SAndrew.Bardsley@arm.com case sizeof(uint32_t): 29010259SAndrew.Bardsley@arm.com panic("No 32bit reads implemented for this device."); 29110259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, 29210259SAndrew.Bardsley@arm.com (uint32_t)pkt->get<uint32_t>()); 29310259SAndrew.Bardsley@arm.com break; 29410259SAndrew.Bardsley@arm.com default: 29510259SAndrew.Bardsley@arm.com panic("invalid access size(?) for PCI configspace!\n"); 29610259SAndrew.Bardsley@arm.com } 29710259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 29810259SAndrew.Bardsley@arm.com return configDelay; 29910259SAndrew.Bardsley@arm.com 30010259SAndrew.Bardsley@arm.com} 30110259SAndrew.Bardsley@arm.com 30210259SAndrew.Bardsley@arm.com 30310259SAndrew.Bardsley@arm.comTick 30410259SAndrew.Bardsley@arm.comIdeController::writeConfig(Packet *pkt) 30510259SAndrew.Bardsley@arm.com{ 30610259SAndrew.Bardsley@arm.com int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 30710259SAndrew.Bardsley@arm.com if (offset < PCI_DEVICE_SPECIFIC) { 30810259SAndrew.Bardsley@arm.com PciDev::writeConfig(pkt); 30910259SAndrew.Bardsley@arm.com } else { 31010259SAndrew.Bardsley@arm.com assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END); 31110259SAndrew.Bardsley@arm.com 31210259SAndrew.Bardsley@arm.com switch (pkt->getSize()) { 31310259SAndrew.Bardsley@arm.com case sizeof(uint8_t): 31410259SAndrew.Bardsley@arm.com switch (offset) { 31510259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_DEV_TIMING: 31610259SAndrew.Bardsley@arm.com config_regs.sidetim = pkt->get<uint8_t>(); 31710259SAndrew.Bardsley@arm.com break; 31810259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_UDMA_CNTRL: 31910259SAndrew.Bardsley@arm.com config_regs.udmactl = pkt->get<uint8_t>(); 32010259SAndrew.Bardsley@arm.com break; 32110259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_IDE_CONFIG: 32210259SAndrew.Bardsley@arm.com config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | 32310259SAndrew.Bardsley@arm.com (pkt->get<uint8_t>()); 32412127Sspwilson2@wisc.edu break; 32512127Sspwilson2@wisc.edu case IDE_CTRL_CONF_IDE_CONFIG+1: 32610259SAndrew.Bardsley@arm.com config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | 32710259SAndrew.Bardsley@arm.com pkt->get<uint8_t>() << 8; 32810259SAndrew.Bardsley@arm.com break; 32910259SAndrew.Bardsley@arm.com default: 33010259SAndrew.Bardsley@arm.com panic("Invalid PCI configuration write for size 1 offset: %#x!\n", 33110259SAndrew.Bardsley@arm.com offset); 33210259SAndrew.Bardsley@arm.com } 33310259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", 33410259SAndrew.Bardsley@arm.com offset, (uint32_t)pkt->get<uint8_t>()); 33510259SAndrew.Bardsley@arm.com break; 33610259SAndrew.Bardsley@arm.com case sizeof(uint16_t): 33710259SAndrew.Bardsley@arm.com switch (offset) { 33810259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_PRIM_TIMING: 33910259SAndrew.Bardsley@arm.com config_regs.idetim0 = pkt->get<uint16_t>(); 34010259SAndrew.Bardsley@arm.com break; 34110259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_SEC_TIMING: 34210259SAndrew.Bardsley@arm.com config_regs.idetim1 = pkt->get<uint16_t>(); 34310259SAndrew.Bardsley@arm.com break; 34410259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_UDMA_TIMING: 34510259SAndrew.Bardsley@arm.com config_regs.udmatim = pkt->get<uint16_t>(); 34610259SAndrew.Bardsley@arm.com break; 34710259SAndrew.Bardsley@arm.com case IDE_CTRL_CONF_IDE_CONFIG: 34810259SAndrew.Bardsley@arm.com config_regs.ideconfig = pkt->get<uint16_t>(); 34910259SAndrew.Bardsley@arm.com break; 35010259SAndrew.Bardsley@arm.com default: 35110259SAndrew.Bardsley@arm.com panic("Invalid PCI configuration write for size 2 offset: %#x!\n", 35210259SAndrew.Bardsley@arm.com offset); 35310259SAndrew.Bardsley@arm.com } 35410259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", 35510259SAndrew.Bardsley@arm.com offset, (uint32_t)pkt->get<uint16_t>()); 35610259SAndrew.Bardsley@arm.com break; 35710259SAndrew.Bardsley@arm.com case sizeof(uint32_t): 35810259SAndrew.Bardsley@arm.com panic("Write of unimplemented PCI config. register: %x\n", offset); 35910259SAndrew.Bardsley@arm.com break; 36010259SAndrew.Bardsley@arm.com default: 36110259SAndrew.Bardsley@arm.com panic("invalid access size(?) for PCI configspace!\n"); 36210259SAndrew.Bardsley@arm.com } 36310259SAndrew.Bardsley@arm.com } 36410259SAndrew.Bardsley@arm.com 36510259SAndrew.Bardsley@arm.com /* Trap command register writes and enable IO/BM as appropriate as well as 36610259SAndrew.Bardsley@arm.com * BARs. */ 36710259SAndrew.Bardsley@arm.com switch(offset) { 36810259SAndrew.Bardsley@arm.com case PCI0_BASE_ADDR0: 36910259SAndrew.Bardsley@arm.com if (BARAddrs[0] != 0) 37010259SAndrew.Bardsley@arm.com pri_cmd_addr = BARAddrs[0]; 37110259SAndrew.Bardsley@arm.com break; 37210259SAndrew.Bardsley@arm.com 37310259SAndrew.Bardsley@arm.com case PCI0_BASE_ADDR1: 37410259SAndrew.Bardsley@arm.com if (BARAddrs[1] != 0) 37510259SAndrew.Bardsley@arm.com pri_ctrl_addr = BARAddrs[1]; 37610259SAndrew.Bardsley@arm.com break; 37710259SAndrew.Bardsley@arm.com 37810259SAndrew.Bardsley@arm.com case PCI0_BASE_ADDR2: 37910259SAndrew.Bardsley@arm.com if (BARAddrs[2] != 0) 38010259SAndrew.Bardsley@arm.com sec_cmd_addr = BARAddrs[2]; 38110259SAndrew.Bardsley@arm.com break; 38210259SAndrew.Bardsley@arm.com 38310259SAndrew.Bardsley@arm.com case PCI0_BASE_ADDR3: 38410259SAndrew.Bardsley@arm.com if (BARAddrs[3] != 0) 38510259SAndrew.Bardsley@arm.com sec_ctrl_addr = BARAddrs[3]; 38610259SAndrew.Bardsley@arm.com break; 38710259SAndrew.Bardsley@arm.com 38810259SAndrew.Bardsley@arm.com case PCI0_BASE_ADDR4: 38910259SAndrew.Bardsley@arm.com if (BARAddrs[4] != 0) 39010259SAndrew.Bardsley@arm.com bmi_addr = BARAddrs[4]; 39110259SAndrew.Bardsley@arm.com break; 39210259SAndrew.Bardsley@arm.com 39310259SAndrew.Bardsley@arm.com case PCI_COMMAND: 39410259SAndrew.Bardsley@arm.com if (letoh(config.command) & PCI_CMD_IOSE) 39510259SAndrew.Bardsley@arm.com io_enabled = true; 39610259SAndrew.Bardsley@arm.com else 39710259SAndrew.Bardsley@arm.com io_enabled = false; 39810259SAndrew.Bardsley@arm.com 39910259SAndrew.Bardsley@arm.com if (letoh(config.command) & PCI_CMD_BME) 40010259SAndrew.Bardsley@arm.com bm_enabled = true; 40110259SAndrew.Bardsley@arm.com else 40210259SAndrew.Bardsley@arm.com bm_enabled = false; 40310259SAndrew.Bardsley@arm.com break; 40410259SAndrew.Bardsley@arm.com } 40510259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 40610259SAndrew.Bardsley@arm.com return configDelay; 40710259SAndrew.Bardsley@arm.com} 40810259SAndrew.Bardsley@arm.com 40910259SAndrew.Bardsley@arm.com 41010259SAndrew.Bardsley@arm.comTick 41110259SAndrew.Bardsley@arm.comIdeController::read(Packet *pkt) 41210259SAndrew.Bardsley@arm.com{ 41310259SAndrew.Bardsley@arm.com Addr offset; 41410259SAndrew.Bardsley@arm.com IdeChannel channel; 41510259SAndrew.Bardsley@arm.com IdeRegType reg_type; 41610259SAndrew.Bardsley@arm.com int disk; 41710259SAndrew.Bardsley@arm.com 41810259SAndrew.Bardsley@arm.com pkt->allocate(); 41910259SAndrew.Bardsley@arm.com if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) 42010259SAndrew.Bardsley@arm.com panic("Bad IDE read size: %d\n", pkt->getSize()); 42110259SAndrew.Bardsley@arm.com 42210259SAndrew.Bardsley@arm.com parseAddr(pkt->getAddr(), offset, channel, reg_type); 42310259SAndrew.Bardsley@arm.com 42410259SAndrew.Bardsley@arm.com if (!io_enabled) { 42510259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 42610259SAndrew.Bardsley@arm.com return pioDelay; 42710259SAndrew.Bardsley@arm.com } 42811435Smitch.hayenga@arm.com 42910259SAndrew.Bardsley@arm.com switch (reg_type) { 43010259SAndrew.Bardsley@arm.com case BMI_BLOCK: 43110259SAndrew.Bardsley@arm.com switch (pkt->getSize()) { 43210259SAndrew.Bardsley@arm.com case sizeof(uint8_t): 43310259SAndrew.Bardsley@arm.com pkt->set(bmi_regs.data[offset]); 43410259SAndrew.Bardsley@arm.com break; 43510259SAndrew.Bardsley@arm.com case sizeof(uint16_t): 43610259SAndrew.Bardsley@arm.com pkt->set(*(uint16_t*)&bmi_regs.data[offset]); 43710259SAndrew.Bardsley@arm.com break; 43810259SAndrew.Bardsley@arm.com case sizeof(uint32_t): 43910259SAndrew.Bardsley@arm.com pkt->set(*(uint32_t*)&bmi_regs.data[offset]); 44010259SAndrew.Bardsley@arm.com break; 44110259SAndrew.Bardsley@arm.com default: 44210259SAndrew.Bardsley@arm.com panic("IDE read of BMI reg invalid size: %#x\n", pkt->getSize()); 44310259SAndrew.Bardsley@arm.com } 44410259SAndrew.Bardsley@arm.com break; 44510259SAndrew.Bardsley@arm.com 44610259SAndrew.Bardsley@arm.com case COMMAND_BLOCK: 44710259SAndrew.Bardsley@arm.com case CONTROL_BLOCK: 44810259SAndrew.Bardsley@arm.com disk = getDisk(channel); 44910259SAndrew.Bardsley@arm.com 45010259SAndrew.Bardsley@arm.com if (disks[disk] == NULL) { 45110259SAndrew.Bardsley@arm.com pkt->set<uint8_t>(0); 45210259SAndrew.Bardsley@arm.com break; 45310259SAndrew.Bardsley@arm.com } 45410259SAndrew.Bardsley@arm.com 45510259SAndrew.Bardsley@arm.com switch (offset) { 45610259SAndrew.Bardsley@arm.com case DATA_OFFSET: 45710259SAndrew.Bardsley@arm.com switch (pkt->getSize()) { 45810259SAndrew.Bardsley@arm.com case sizeof(uint16_t): 45910259SAndrew.Bardsley@arm.com disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); 46010259SAndrew.Bardsley@arm.com break; 46110259SAndrew.Bardsley@arm.com 46210259SAndrew.Bardsley@arm.com case sizeof(uint32_t): 46310259SAndrew.Bardsley@arm.com disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); 46410259SAndrew.Bardsley@arm.com disks[disk]->read(offset, reg_type, 46510259SAndrew.Bardsley@arm.com pkt->getPtr<uint8_t>() + sizeof(uint16_t)); 46610259SAndrew.Bardsley@arm.com break; 46710259SAndrew.Bardsley@arm.com 46810259SAndrew.Bardsley@arm.com default: 46910259SAndrew.Bardsley@arm.com panic("IDE read of data reg invalid size: %#x\n", pkt->getSize()); 47010259SAndrew.Bardsley@arm.com } 47110259SAndrew.Bardsley@arm.com break; 47210259SAndrew.Bardsley@arm.com default: 47310259SAndrew.Bardsley@arm.com if (pkt->getSize() == sizeof(uint8_t)) { 47410259SAndrew.Bardsley@arm.com disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>()); 47510259SAndrew.Bardsley@arm.com } else 47610259SAndrew.Bardsley@arm.com panic("IDE read of command reg of invalid size: %#x\n", pkt->getSize()); 47710259SAndrew.Bardsley@arm.com } 47810259SAndrew.Bardsley@arm.com break; 47910259SAndrew.Bardsley@arm.com default: 48010259SAndrew.Bardsley@arm.com panic("IDE controller read of unknown register block type!\n"); 48110259SAndrew.Bardsley@arm.com } 48210368SAndrew.Bardsley@arm.com if (pkt->getSize() == 1) 48310368SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 48410259SAndrew.Bardsley@arm.com offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>()); 48510259SAndrew.Bardsley@arm.com else if (pkt->getSize() == 2) 48610259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 48710259SAndrew.Bardsley@arm.com offset, pkt->getSize(), pkt->get<uint16_t>()); 48810259SAndrew.Bardsley@arm.com else 48910259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", 49010259SAndrew.Bardsley@arm.com offset, pkt->getSize(), pkt->get<uint32_t>()); 49110259SAndrew.Bardsley@arm.com 49210259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 49310259SAndrew.Bardsley@arm.com return pioDelay; 49410259SAndrew.Bardsley@arm.com} 49510259SAndrew.Bardsley@arm.com 49610259SAndrew.Bardsley@arm.comTick 49710259SAndrew.Bardsley@arm.comIdeController::write(Packet *pkt) 49810259SAndrew.Bardsley@arm.com{ 49910259SAndrew.Bardsley@arm.com Addr offset; 50010259SAndrew.Bardsley@arm.com IdeChannel channel; 50110259SAndrew.Bardsley@arm.com IdeRegType reg_type; 50210259SAndrew.Bardsley@arm.com int disk; 50310259SAndrew.Bardsley@arm.com uint8_t oldVal, newVal; 50410259SAndrew.Bardsley@arm.com 50510259SAndrew.Bardsley@arm.com parseAddr(pkt->getAddr(), offset, channel, reg_type); 50610259SAndrew.Bardsley@arm.com 50710259SAndrew.Bardsley@arm.com if (!io_enabled) { 50810259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 50910259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "io not enabled\n"); 51010259SAndrew.Bardsley@arm.com return pioDelay; 51110259SAndrew.Bardsley@arm.com } 51210259SAndrew.Bardsley@arm.com 51310259SAndrew.Bardsley@arm.com switch (reg_type) { 51410259SAndrew.Bardsley@arm.com case BMI_BLOCK: 51510259SAndrew.Bardsley@arm.com if (!bm_enabled) { 51610259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 51710259SAndrew.Bardsley@arm.com return pioDelay; 51810259SAndrew.Bardsley@arm.com } 51910259SAndrew.Bardsley@arm.com 52010259SAndrew.Bardsley@arm.com switch (offset) { 52110259SAndrew.Bardsley@arm.com // Bus master IDE command register 52210259SAndrew.Bardsley@arm.com case BMIC1: 52310259SAndrew.Bardsley@arm.com case BMIC0: 52410259SAndrew.Bardsley@arm.com if (pkt->getSize() != sizeof(uint8_t)) 52510259SAndrew.Bardsley@arm.com panic("Invalid BMIC write size: %x\n", pkt->getSize()); 52610259SAndrew.Bardsley@arm.com 52710259SAndrew.Bardsley@arm.com // select the current disk based on DEV bit 52810259SAndrew.Bardsley@arm.com disk = getDisk(channel); 52910259SAndrew.Bardsley@arm.com 53010259SAndrew.Bardsley@arm.com oldVal = bmi_regs.chan[channel].bmic; 53110259SAndrew.Bardsley@arm.com newVal = pkt->get<uint8_t>(); 53210259SAndrew.Bardsley@arm.com 53310259SAndrew.Bardsley@arm.com // if a DMA transfer is in progress, R/W control cannot change 53410259SAndrew.Bardsley@arm.com if (oldVal & SSBM) { 53510259SAndrew.Bardsley@arm.com if ((oldVal & RWCON) ^ (newVal & RWCON)) { 53610259SAndrew.Bardsley@arm.com (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON; 53710259SAndrew.Bardsley@arm.com } 53810259SAndrew.Bardsley@arm.com } 53910259SAndrew.Bardsley@arm.com 54010259SAndrew.Bardsley@arm.com // see if the start/stop bit is being changed 54110259SAndrew.Bardsley@arm.com if ((oldVal & SSBM) ^ (newVal & SSBM)) { 54210259SAndrew.Bardsley@arm.com if (oldVal & SSBM) { 54310259SAndrew.Bardsley@arm.com // stopping DMA transfer 54410259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); 54510259SAndrew.Bardsley@arm.com 54610259SAndrew.Bardsley@arm.com // clear the BMIDEA bit 54710259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmis = 54810259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmis & ~BMIDEA; 54910259SAndrew.Bardsley@arm.com 55010259SAndrew.Bardsley@arm.com if (disks[disk] == NULL) 55110259SAndrew.Bardsley@arm.com panic("DMA stop for disk %d which does not exist\n", 55210259SAndrew.Bardsley@arm.com disk); 55310259SAndrew.Bardsley@arm.com 55410259SAndrew.Bardsley@arm.com // inform the disk of the DMA transfer abort 55510259SAndrew.Bardsley@arm.com disks[disk]->abortDma(); 55610259SAndrew.Bardsley@arm.com } else { 55710259SAndrew.Bardsley@arm.com // starting DMA transfer 55810259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "Starting DMA transfer\n"); 55910259SAndrew.Bardsley@arm.com 56010259SAndrew.Bardsley@arm.com // set the BMIDEA bit 56110259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmis = 56210259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmis | BMIDEA; 56310259SAndrew.Bardsley@arm.com 56410259SAndrew.Bardsley@arm.com if (disks[disk] == NULL) 56510259SAndrew.Bardsley@arm.com panic("DMA start for disk %d which does not exist\n", 56610563Sandreas.hansson@arm.com disk); 56710259SAndrew.Bardsley@arm.com 56810259SAndrew.Bardsley@arm.com // inform the disk of the DMA transfer start 56910259SAndrew.Bardsley@arm.com disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp)); 57010259SAndrew.Bardsley@arm.com } 57110259SAndrew.Bardsley@arm.com } 57210259SAndrew.Bardsley@arm.com 57310259SAndrew.Bardsley@arm.com // update the register value 57410259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmic = newVal; 57510259SAndrew.Bardsley@arm.com break; 57610259SAndrew.Bardsley@arm.com 57710259SAndrew.Bardsley@arm.com // Bus master IDE status register 57810259SAndrew.Bardsley@arm.com case BMIS0: 57910259SAndrew.Bardsley@arm.com case BMIS1: 58010259SAndrew.Bardsley@arm.com if (pkt->getSize() != sizeof(uint8_t)) 58110259SAndrew.Bardsley@arm.com panic("Invalid BMIS write size: %x\n", pkt->getSize()); 58210259SAndrew.Bardsley@arm.com 58310259SAndrew.Bardsley@arm.com oldVal = bmi_regs.chan[channel].bmis; 58410259SAndrew.Bardsley@arm.com newVal = pkt->get<uint8_t>(); 58510259SAndrew.Bardsley@arm.com 58610259SAndrew.Bardsley@arm.com // the BMIDEA bit is RO 58710259SAndrew.Bardsley@arm.com newVal |= (oldVal & BMIDEA); 58810259SAndrew.Bardsley@arm.com 58910259SAndrew.Bardsley@arm.com // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each 59010259SAndrew.Bardsley@arm.com if ((oldVal & IDEINTS) && (newVal & IDEINTS)) 59110259SAndrew.Bardsley@arm.com newVal &= ~IDEINTS; // clear the interrupt? 59210259SAndrew.Bardsley@arm.com else 59310259SAndrew.Bardsley@arm.com (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS; 59410259SAndrew.Bardsley@arm.com 59510259SAndrew.Bardsley@arm.com if ((oldVal & IDEDMAE) && (newVal & IDEDMAE)) 59610259SAndrew.Bardsley@arm.com newVal &= ~IDEDMAE; 59710259SAndrew.Bardsley@arm.com else 59810259SAndrew.Bardsley@arm.com (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; 59910259SAndrew.Bardsley@arm.com 60010259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmis = newVal; 60110259SAndrew.Bardsley@arm.com break; 60210259SAndrew.Bardsley@arm.com 60310259SAndrew.Bardsley@arm.com // Bus master IDE descriptor table pointer register 60410259SAndrew.Bardsley@arm.com case BMIDTP0: 60510259SAndrew.Bardsley@arm.com case BMIDTP1: 60610259SAndrew.Bardsley@arm.com { 60710259SAndrew.Bardsley@arm.com if (pkt->getSize() != sizeof(uint32_t)) 60810259SAndrew.Bardsley@arm.com panic("Invalid BMIDTP write size: %x\n", pkt->getSize()); 60910259SAndrew.Bardsley@arm.com 61010259SAndrew.Bardsley@arm.com bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3); 61110259SAndrew.Bardsley@arm.com } 61210259SAndrew.Bardsley@arm.com break; 61310259SAndrew.Bardsley@arm.com 61410259SAndrew.Bardsley@arm.com default: 61510259SAndrew.Bardsley@arm.com if (pkt->getSize() != sizeof(uint8_t) && 61610259SAndrew.Bardsley@arm.com pkt->getSize() != sizeof(uint16_t) && 61710259SAndrew.Bardsley@arm.com pkt->getSize() != sizeof(uint32_t)) 61810259SAndrew.Bardsley@arm.com panic("IDE controller write of invalid write size: %x\n", 61910259SAndrew.Bardsley@arm.com pkt->getSize()); 62010259SAndrew.Bardsley@arm.com 62110259SAndrew.Bardsley@arm.com // do a default copy of data into the registers 62210259SAndrew.Bardsley@arm.com memcpy(&bmi_regs.data[offset], pkt->getPtr<uint8_t>(), pkt->getSize()); 62310259SAndrew.Bardsley@arm.com } 62410259SAndrew.Bardsley@arm.com break; 62510259SAndrew.Bardsley@arm.com case COMMAND_BLOCK: 62610259SAndrew.Bardsley@arm.com if (offset == IDE_SELECT_OFFSET) { 62710259SAndrew.Bardsley@arm.com uint8_t *devBit = &dev[channel]; 62810259SAndrew.Bardsley@arm.com *devBit = (letoh(pkt->get<uint8_t>()) & IDE_SELECT_DEV_BIT) ? 1 : 0; 62910259SAndrew.Bardsley@arm.com } 63010259SAndrew.Bardsley@arm.com // fall-through ok! 63110259SAndrew.Bardsley@arm.com case CONTROL_BLOCK: 63210259SAndrew.Bardsley@arm.com disk = getDisk(channel); 63310259SAndrew.Bardsley@arm.com 63410259SAndrew.Bardsley@arm.com if (disks[disk] == NULL) 63510259SAndrew.Bardsley@arm.com break; 63610259SAndrew.Bardsley@arm.com 63710259SAndrew.Bardsley@arm.com switch (offset) { 63810259SAndrew.Bardsley@arm.com case DATA_OFFSET: 63910259SAndrew.Bardsley@arm.com switch (pkt->getSize()) { 64010259SAndrew.Bardsley@arm.com case sizeof(uint16_t): 64110259SAndrew.Bardsley@arm.com disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); 64210259SAndrew.Bardsley@arm.com break; 64310259SAndrew.Bardsley@arm.com 64410259SAndrew.Bardsley@arm.com case sizeof(uint32_t): 64510259SAndrew.Bardsley@arm.com disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); 64610259SAndrew.Bardsley@arm.com disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>() + 64710259SAndrew.Bardsley@arm.com sizeof(uint16_t)); 64810259SAndrew.Bardsley@arm.com break; 64910259SAndrew.Bardsley@arm.com default: 65010259SAndrew.Bardsley@arm.com panic("IDE write of data reg invalid size: %#x\n", pkt->getSize()); 65110259SAndrew.Bardsley@arm.com } 65210259SAndrew.Bardsley@arm.com break; 65310259SAndrew.Bardsley@arm.com default: 65410259SAndrew.Bardsley@arm.com if (pkt->getSize() == sizeof(uint8_t)) { 65510259SAndrew.Bardsley@arm.com disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>()); 65610259SAndrew.Bardsley@arm.com } else 65710259SAndrew.Bardsley@arm.com panic("IDE write of command reg of invalid size: %#x\n", pkt->getSize()); 65810259SAndrew.Bardsley@arm.com } 65910259SAndrew.Bardsley@arm.com break; 66010259SAndrew.Bardsley@arm.com default: 66110259SAndrew.Bardsley@arm.com panic("IDE controller write of unknown register block type!\n"); 66210259SAndrew.Bardsley@arm.com } 66310259SAndrew.Bardsley@arm.com 66410259SAndrew.Bardsley@arm.com if (pkt->getSize() == 1) 66510259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 66610259SAndrew.Bardsley@arm.com offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>()); 66710259SAndrew.Bardsley@arm.com else if (pkt->getSize() == 2) 66810259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 66910259SAndrew.Bardsley@arm.com offset, pkt->getSize(), pkt->get<uint16_t>()); 67010259SAndrew.Bardsley@arm.com else 67110259SAndrew.Bardsley@arm.com DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", 67210259SAndrew.Bardsley@arm.com offset, pkt->getSize(), pkt->get<uint32_t>()); 67310259SAndrew.Bardsley@arm.com 67410259SAndrew.Bardsley@arm.com 67510259SAndrew.Bardsley@arm.com pkt->result = Packet::Success; 67610259SAndrew.Bardsley@arm.com return pioDelay; 67710259SAndrew.Bardsley@arm.com} 67810259SAndrew.Bardsley@arm.com 67910259SAndrew.Bardsley@arm.com//// 68010259SAndrew.Bardsley@arm.com// Serialization 68110259SAndrew.Bardsley@arm.com//// 68211567Smitch.hayenga@arm.com 68311567Smitch.hayenga@arm.comvoid 68410259SAndrew.Bardsley@arm.comIdeController::serialize(std::ostream &os) 68510259SAndrew.Bardsley@arm.com{ 68610259SAndrew.Bardsley@arm.com // Serialize the PciDev base class 68710259SAndrew.Bardsley@arm.com PciDev::serialize(os); 68810259SAndrew.Bardsley@arm.com 68910259SAndrew.Bardsley@arm.com // Serialize register addresses and sizes 69010259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(pri_cmd_addr); 69110259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(pri_cmd_size); 69210259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(pri_ctrl_addr); 69310259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(pri_ctrl_size); 69410259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(sec_cmd_addr); 69510259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(sec_cmd_size); 69610259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(sec_ctrl_addr); 69710259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(sec_ctrl_size); 69810259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(bmi_addr); 69910259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(bmi_size); 70010259SAndrew.Bardsley@arm.com 70110259SAndrew.Bardsley@arm.com // Serialize registers 70210259SAndrew.Bardsley@arm.com SERIALIZE_ARRAY(bmi_regs.data, 70310259SAndrew.Bardsley@arm.com sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); 70410259SAndrew.Bardsley@arm.com SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); 70510259SAndrew.Bardsley@arm.com SERIALIZE_ARRAY(config_regs.data, 70610259SAndrew.Bardsley@arm.com sizeof(config_regs.data) / sizeof(config_regs.data[0])); 70710259SAndrew.Bardsley@arm.com 70810259SAndrew.Bardsley@arm.com // Serialize internal state 70910259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(io_enabled); 71010259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(bm_enabled); 71110259SAndrew.Bardsley@arm.com SERIALIZE_ARRAY(cmd_in_progress, 71210259SAndrew.Bardsley@arm.com sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); 71310259SAndrew.Bardsley@arm.com} 71410259SAndrew.Bardsley@arm.com 71510259SAndrew.Bardsley@arm.comvoid 71610259SAndrew.Bardsley@arm.comIdeController::unserialize(Checkpoint *cp, const std::string §ion) 71710259SAndrew.Bardsley@arm.com{ 71810259SAndrew.Bardsley@arm.com // Unserialize the PciDev base class 71910259SAndrew.Bardsley@arm.com PciDev::unserialize(cp, section); 72010259SAndrew.Bardsley@arm.com 72110259SAndrew.Bardsley@arm.com // Unserialize register addresses and sizes 72210259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(pri_cmd_addr); 72310259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(pri_cmd_size); 72410259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(pri_ctrl_addr); 72510259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(pri_ctrl_size); 72610259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(sec_cmd_addr); 72710259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(sec_cmd_size); 72810259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(sec_ctrl_addr); 72910259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(sec_ctrl_size); 73010259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(bmi_addr); 73110259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(bmi_size); 73210259SAndrew.Bardsley@arm.com 73310259SAndrew.Bardsley@arm.com // Unserialize registers 73410259SAndrew.Bardsley@arm.com UNSERIALIZE_ARRAY(bmi_regs.data, 73510259SAndrew.Bardsley@arm.com sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); 73610259SAndrew.Bardsley@arm.com UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); 73710581SAndrew.Bardsley@arm.com UNSERIALIZE_ARRAY(config_regs.data, 73810581SAndrew.Bardsley@arm.com sizeof(config_regs.data) / sizeof(config_regs.data[0])); 73910581SAndrew.Bardsley@arm.com 74010581SAndrew.Bardsley@arm.com // Unserialize internal state 74110581SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(io_enabled); 74210581SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(bm_enabled); 74310581SAndrew.Bardsley@arm.com UNSERIALIZE_ARRAY(cmd_in_progress, 74410581SAndrew.Bardsley@arm.com sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); 74510581SAndrew.Bardsley@arm.com pioPort->sendStatusChange(Port::RangeChange); 74610259SAndrew.Bardsley@arm.com} 74710259SAndrew.Bardsley@arm.com 74810259SAndrew.Bardsley@arm.com#ifndef DOXYGEN_SHOULD_SKIP_THIS 74910259SAndrew.Bardsley@arm.com 75010259SAndrew.Bardsley@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) 75110259SAndrew.Bardsley@arm.com 75210259SAndrew.Bardsley@arm.com SimObjectParam<System *> system; 75310259SAndrew.Bardsley@arm.com SimObjectParam<Platform *> platform; 75410259SAndrew.Bardsley@arm.com SimObjectParam<PciConfigData *> configdata; 75510259SAndrew.Bardsley@arm.com Param<uint32_t> pci_bus; 75610259SAndrew.Bardsley@arm.com Param<uint32_t> pci_dev; 75710259SAndrew.Bardsley@arm.com Param<uint32_t> pci_func; 75810259SAndrew.Bardsley@arm.com Param<Tick> pio_latency; 75910259SAndrew.Bardsley@arm.com SimObjectVectorParam<IdeDisk *> disks; 76010259SAndrew.Bardsley@arm.com 76110259SAndrew.Bardsley@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(IdeController) 76210259SAndrew.Bardsley@arm.com 76310259SAndrew.Bardsley@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) 76410259SAndrew.Bardsley@arm.com 76510259SAndrew.Bardsley@arm.com INIT_PARAM(system, "System pointer"), 76610259SAndrew.Bardsley@arm.com INIT_PARAM(platform, "Platform pointer"), 76710259SAndrew.Bardsley@arm.com INIT_PARAM(configdata, "PCI Config data"), 76810259SAndrew.Bardsley@arm.com INIT_PARAM(pci_bus, "PCI bus ID"), 76910259SAndrew.Bardsley@arm.com INIT_PARAM(pci_dev, "PCI device number"), 77010259SAndrew.Bardsley@arm.com INIT_PARAM(pci_func, "PCI function code"), 77110259SAndrew.Bardsley@arm.com INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 77210259SAndrew.Bardsley@arm.com INIT_PARAM(disks, "IDE disks attached to this controller") 77310259SAndrew.Bardsley@arm.com 77410259SAndrew.Bardsley@arm.comEND_INIT_SIM_OBJECT_PARAMS(IdeController) 77510259SAndrew.Bardsley@arm.com 77610259SAndrew.Bardsley@arm.comCREATE_SIM_OBJECT(IdeController) 77710259SAndrew.Bardsley@arm.com{ 77810259SAndrew.Bardsley@arm.com IdeController::Params *params = new IdeController::Params; 77910259SAndrew.Bardsley@arm.com params->name = getInstanceName(); 78010259SAndrew.Bardsley@arm.com params->platform = platform; 78110259SAndrew.Bardsley@arm.com params->system = system; 78210259SAndrew.Bardsley@arm.com params->configData = configdata; 78310259SAndrew.Bardsley@arm.com params->busNum = pci_bus; 78410259SAndrew.Bardsley@arm.com params->deviceNum = pci_dev; 78510259SAndrew.Bardsley@arm.com params->functionNum = pci_func; 78610259SAndrew.Bardsley@arm.com params->pio_delay = pio_latency; 78710259SAndrew.Bardsley@arm.com params->disks = disks; 78810259SAndrew.Bardsley@arm.com return new IdeController(params); 78910259SAndrew.Bardsley@arm.com} 79010259SAndrew.Bardsley@arm.com 79110259SAndrew.Bardsley@arm.comREGISTER_SIM_OBJECT("IdeController", IdeController) 79210259SAndrew.Bardsley@arm.com 79310259SAndrew.Bardsley@arm.com#endif //DOXYGEN_SHOULD_SKIP_THIS 79410259SAndrew.Bardsley@arm.com