1848SN/A/* 29956SN/A * Copyright (c) 2013 ARM Limited 39956SN/A * All rights reserved 49956SN/A * 59956SN/A * The license below extends only to copyright in the software and shall 69956SN/A * not be construed as granting a license to any other intellectual 79956SN/A * property including but not limited to intellectual property relating 89956SN/A * to a hardware implementation of the functionality of the software 99956SN/A * licensed hereunder. You may use the software subject to the license 109956SN/A * terms below provided that you ensure that this notice is replicated 119956SN/A * unmodified and in its entirety in all distributions of the software, 129956SN/A * modified or unmodified, in source code or in binary form. 139956SN/A * 141762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 15848SN/A * All rights reserved. 16848SN/A * 17848SN/A * Redistribution and use in source and binary forms, with or without 18848SN/A * modification, are permitted provided that the following conditions are 19848SN/A * met: redistributions of source code must retain the above copyright 20848SN/A * notice, this list of conditions and the following disclaimer; 21848SN/A * redistributions in binary form must reproduce the above copyright 22848SN/A * notice, this list of conditions and the following disclaimer in the 23848SN/A * documentation and/or other materials provided with the distribution; 24848SN/A * neither the name of the copyright holders nor the names of its 25848SN/A * contributors may be used to endorse or promote products derived from 26848SN/A * this software without specific prior written permission. 27848SN/A * 28848SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29848SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30848SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31848SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32848SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33848SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34848SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35848SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36848SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37848SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38848SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Andrew Schultz 41848SN/A */ 42848SN/A 43848SN/A/** @file 44848SN/A * Device model for an IDE disk 45848SN/A */ 46848SN/A 4711264Sandreas.sandberg@arm.com#ifndef __DEV_STORAGE_IDE_DISK_HH__ 4811264Sandreas.sandberg@arm.com#define __DEV_STORAGE_IDE_DISK_HH__ 49848SN/A 502275SN/A#include "base/statistics.hh" 51848SN/A#include "dev/io_device.hh" 5211264Sandreas.sandberg@arm.com#include "dev/storage/disk_image.hh" 5311264Sandreas.sandberg@arm.com#include "dev/storage/ide_atareg.h" 5411264Sandreas.sandberg@arm.com#include "dev/storage/ide_ctrl.hh" 5511264Sandreas.sandberg@arm.com#include "dev/storage/ide_wdcreg.h" 568229SN/A#include "params/IdeDisk.hh" 57849SN/A#include "sim/eventq.hh" 58848SN/A 593090SN/Aclass ChunkGenerator; 603090SN/A 618522SN/A#define DMA_BACKOFF_PERIOD 200 62849SN/A 638522SN/A#define MAX_DMA_SIZE 0x20000 // 128K 648522SN/A#define MAX_SINGLE_DMA_SIZE 0x10000 658522SN/A#define MAX_MULTSECT (128) 66849SN/A 67849SN/A#define PRD_BASE_MASK 0xfffffffe 68849SN/A#define PRD_COUNT_MASK 0xfffe 69849SN/A#define PRD_EOT_MASK 0x8000 70849SN/A 71849SN/Atypedef struct PrdEntry { 72849SN/A uint32_t baseAddr; 73849SN/A uint16_t byteCount; 74849SN/A uint16_t endOfTable; 75849SN/A} PrdEntry_t; 76849SN/A 77849SN/Aclass PrdTableEntry { 78849SN/A public: 79849SN/A PrdEntry_t entry; 80849SN/A 81849SN/A uint32_t getBaseAddr() 82849SN/A { 83849SN/A return (entry.baseAddr & PRD_BASE_MASK); 84849SN/A } 85849SN/A 86896SN/A uint32_t getByteCount() 87849SN/A { 888522SN/A return ((entry.byteCount == 0) ? MAX_SINGLE_DMA_SIZE : 89849SN/A (entry.byteCount & PRD_COUNT_MASK)); 90849SN/A } 91849SN/A 92849SN/A uint16_t getEOT() 93849SN/A { 94849SN/A return (entry.endOfTable & PRD_EOT_MASK); 95849SN/A } 96849SN/A}; 97849SN/A 98849SN/A#define DATA_OFFSET (0) 99849SN/A#define ERROR_OFFSET (1) 100849SN/A#define FEATURES_OFFSET (1) 101849SN/A#define NSECTOR_OFFSET (2) 102849SN/A#define SECTOR_OFFSET (3) 103849SN/A#define LCYL_OFFSET (4) 104849SN/A#define HCYL_OFFSET (5) 105849SN/A#define SELECT_OFFSET (6) 1061817SN/A#define DRIVE_OFFSET (6) 107849SN/A#define STATUS_OFFSET (7) 108849SN/A#define COMMAND_OFFSET (7) 109849SN/A 110849SN/A#define CONTROL_OFFSET (2) 111849SN/A#define ALTSTAT_OFFSET (2) 112849SN/A 113849SN/A#define SELECT_DEV_BIT 0x10 114849SN/A#define CONTROL_RST_BIT 0x04 115849SN/A#define CONTROL_IEN_BIT 0x02 116849SN/A#define STATUS_BSY_BIT 0x80 117849SN/A#define STATUS_DRDY_BIT 0x40 118849SN/A#define STATUS_DRQ_BIT 0x08 119893SN/A#define STATUS_SEEK_BIT 0x10 120893SN/A#define STATUS_DF_BIT 0x20 121864SN/A#define DRIVE_LBA_BIT 0x40 122849SN/A 123849SN/A#define DEV0 (0) 124849SN/A#define DEV1 (1) 125849SN/A 126849SN/Atypedef struct CommandReg { 1271817SN/A uint16_t data; 1281817SN/A uint8_t error; 129849SN/A uint8_t sec_count; 130849SN/A uint8_t sec_num; 131849SN/A uint8_t cyl_low; 132849SN/A uint8_t cyl_high; 133849SN/A union { 134849SN/A uint8_t drive; 135849SN/A uint8_t head; 136849SN/A }; 137893SN/A uint8_t command; 138849SN/A} CommandReg_t; 139849SN/A 140864SN/Atypedef enum Events { 141864SN/A None = 0, 142864SN/A Transfer, 143864SN/A ReadWait, 144864SN/A WriteWait, 145864SN/A PrdRead, 146864SN/A DmaRead, 147864SN/A DmaWrite 148864SN/A} Events_t; 149864SN/A 150849SN/Atypedef enum DevAction { 151849SN/A ACT_NONE = 0, 152849SN/A ACT_CMD_WRITE, 153849SN/A ACT_CMD_COMPLETE, 154849SN/A ACT_CMD_ERROR, 155893SN/A ACT_SELECT_WRITE, 156849SN/A ACT_STAT_READ, 157849SN/A ACT_DATA_READY, 158849SN/A ACT_DATA_READ_BYTE, 159849SN/A ACT_DATA_READ_SHORT, 160849SN/A ACT_DATA_WRITE_BYTE, 161849SN/A ACT_DATA_WRITE_SHORT, 162849SN/A ACT_DMA_READY, 163893SN/A ACT_DMA_DONE, 164893SN/A ACT_SRST_SET, 165893SN/A ACT_SRST_CLEAR 166849SN/A} DevAction_t; 167849SN/A 168849SN/Atypedef enum DevState { 169849SN/A // Device idle 170849SN/A Device_Idle_S = 0, 171849SN/A Device_Idle_SI, 172849SN/A Device_Idle_NS, 173849SN/A 174893SN/A // Software reset 175893SN/A Device_Srst, 176893SN/A 177849SN/A // Non-data commands 178849SN/A Command_Execution, 179849SN/A 180849SN/A // PIO data-in (data to host) 181849SN/A Prepare_Data_In, 182849SN/A Data_Ready_INTRQ_In, 183849SN/A Transfer_Data_In, 184849SN/A 185849SN/A // PIO data-out (data from host) 186849SN/A Prepare_Data_Out, 187849SN/A Data_Ready_INTRQ_Out, 188849SN/A Transfer_Data_Out, 189849SN/A 190849SN/A // DMA protocol 191849SN/A Prepare_Data_Dma, 1929956SN/A Transfer_Data_Dma, 1939956SN/A Device_Dma_Abort 194849SN/A} DevState_t; 195849SN/A 196849SN/Atypedef enum DmaState { 197849SN/A Dma_Idle = 0, 198849SN/A Dma_Start, 199849SN/A Dma_Transfer 200849SN/A} DmaState_t; 201849SN/A 202848SN/Aclass IdeController; 203848SN/A 204848SN/A/** 205849SN/A * IDE Disk device model 206848SN/A */ 207848SN/Aclass IdeDisk : public SimObject 208848SN/A{ 209848SN/A protected: 210848SN/A /** The IDE controller for this disk. */ 211848SN/A IdeController *ctrl; 212848SN/A /** The image that contains the data of this disk. */ 213848SN/A DiskImage *image; 214848SN/A 215848SN/A protected: 216864SN/A /** The disk delay in microseconds. */ 217848SN/A int diskDelay; 218848SN/A 219849SN/A private: 220849SN/A /** Drive identification structure for this disk */ 2211722SN/A struct ataparams driveID; 222849SN/A /** Data buffer for transfers */ 223849SN/A uint8_t *dataBuffer; 224893SN/A /** Number of bytes in command data transfer */ 225893SN/A uint32_t cmdBytes; 226849SN/A /** Number of bytes left in command data transfer */ 227849SN/A uint32_t cmdBytesLeft; 228849SN/A /** Number of bytes left in DRQ block */ 229849SN/A uint32_t drqBytesLeft; 230849SN/A /** Current sector in access */ 231849SN/A uint32_t curSector; 232849SN/A /** Command block registers */ 233849SN/A CommandReg_t cmdReg; 234893SN/A /** Status register */ 235893SN/A uint8_t status; 236849SN/A /** Interrupt enable bit */ 237849SN/A bool nIENBit; 238849SN/A /** Device state */ 239849SN/A DevState_t devState; 240849SN/A /** Dma state */ 241849SN/A DmaState_t dmaState; 242849SN/A /** Dma transaction is a read */ 243849SN/A bool dmaRead; 244849SN/A /** PRD table base address */ 245849SN/A uint32_t curPrdAddr; 246849SN/A /** PRD entry */ 247849SN/A PrdTableEntry curPrd; 248849SN/A /** Device ID (master=0/slave=1) */ 249849SN/A int devID; 250849SN/A /** Interrupt pending */ 251849SN/A bool intrPending; 2529956SN/A /** DMA Aborted */ 2539956SN/A bool dmaAborted; 254849SN/A 2555999SN/A Stats::Scalar dmaReadFullPages; 2565999SN/A Stats::Scalar dmaReadBytes; 2575999SN/A Stats::Scalar dmaReadTxs; 2585999SN/A Stats::Scalar dmaWriteFullPages; 2595999SN/A Stats::Scalar dmaWriteBytes; 2605999SN/A Stats::Scalar dmaWriteTxs; 2612275SN/A 262848SN/A public: 2635034SN/A typedef IdeDiskParams Params; 2645034SN/A IdeDisk(const Params *p); 265848SN/A 266848SN/A /** 267848SN/A * Delete the data buffer. 268848SN/A */ 269848SN/A ~IdeDisk(); 270848SN/A 271848SN/A /** 272893SN/A * Reset the device state 273893SN/A */ 274893SN/A void reset(int id); 275893SN/A 276893SN/A /** 2772629SN/A * Register Statistics 2782629SN/A */ 27911169SN/A void regStats() override; 2802629SN/A 2812629SN/A /** 282848SN/A * Set the controller for this device 283848SN/A * @param c The IDE controller 284848SN/A */ 2852565SN/A void setController(IdeController *c) { 286848SN/A if (ctrl) panic("Cannot change the controller once set!\n"); 287848SN/A ctrl = c; 288848SN/A } 289848SN/A 290849SN/A // Device register read/write 2915772SN/A void readCommand(const Addr offset, int size, uint8_t *data); 2925772SN/A void readControl(const Addr offset, int size, uint8_t *data); 2935772SN/A void writeCommand(const Addr offset, int size, const uint8_t *data); 2945772SN/A void writeControl(const Addr offset, int size, const uint8_t *data); 295848SN/A 296849SN/A // Start/abort functions 297849SN/A void startDma(const uint32_t &prdTableBase); 298849SN/A void abortDma(); 299849SN/A 300849SN/A private: 301849SN/A void startCommand(); 302849SN/A 303849SN/A // Interrupt management 304849SN/A void intrPost(); 305849SN/A void intrClear(); 306849SN/A 307849SN/A // DMA stuff 308849SN/A void doDmaTransfer(); 30912087Sspwilson2@wisc.edu EventFunctionWrapper dmaTransferEvent; 310849SN/A 3112565SN/A void doDmaDataRead(); 3122565SN/A 313849SN/A void doDmaRead(); 3142565SN/A ChunkGenerator *dmaReadCG; 31512087Sspwilson2@wisc.edu EventFunctionWrapper dmaReadWaitEvent; 316849SN/A 3172565SN/A void doDmaDataWrite(); 3182565SN/A 319849SN/A void doDmaWrite(); 3202565SN/A ChunkGenerator *dmaWriteCG; 32112087Sspwilson2@wisc.edu EventFunctionWrapper dmaWriteWaitEvent; 322849SN/A 323849SN/A void dmaPrdReadDone(); 32412087Sspwilson2@wisc.edu EventFunctionWrapper dmaPrdReadEvent; 325849SN/A 326849SN/A void dmaReadDone(); 32712087Sspwilson2@wisc.edu EventFunctionWrapper dmaReadEvent; 328849SN/A 329849SN/A void dmaWriteDone(); 33012087Sspwilson2@wisc.edu EventFunctionWrapper dmaWriteEvent; 331849SN/A 332849SN/A // Disk image read/write 333849SN/A void readDisk(uint32_t sector, uint8_t *data); 334849SN/A void writeDisk(uint32_t sector, uint8_t *data); 335849SN/A 336849SN/A // State machine management 337849SN/A void updateState(DevAction_t action); 338849SN/A 339849SN/A // Utility functions 340893SN/A bool isBSYSet() { return (status & STATUS_BSY_BIT); } 341849SN/A bool isIENSet() { return nIENBit; } 342929SN/A bool isDEVSelect(); 343849SN/A 344849SN/A void setComplete() 345849SN/A { 346849SN/A // clear out the status byte 347893SN/A status = 0; 348849SN/A // set the DRDY bit 349893SN/A status |= STATUS_DRDY_BIT; 350893SN/A // set the SEEK bit 351893SN/A status |= STATUS_SEEK_BIT; 352849SN/A } 353849SN/A 354849SN/A uint32_t getLBABase() 355849SN/A { 356849SN/A return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) | 357849SN/A (cmdReg.cyl_low << 8) | (cmdReg.sec_num)); 358849SN/A } 359848SN/A 360864SN/A inline Addr pciToDma(Addr pciAddr); 361864SN/A 36211168SN/A void serialize(CheckpointOut &cp) const override; 36311168SN/A void unserialize(CheckpointIn &cp) override; 364848SN/A}; 365848SN/A 366848SN/A 36711264Sandreas.sandberg@arm.com#endif // __DEV_STORAGE_IDE_DISK_HH__ 368