io_device.hh revision 2512
16899SN/A/* 28851Sandreas.hansson@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 38851Sandreas.hansson@arm.com * All rights reserved. 48851Sandreas.hansson@arm.com * 58851Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68851Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78851Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88851Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98851Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108851Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118851Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128851Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138851Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 146899SN/A * this software without specific prior written permission. 157553SN/A * 166899SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176899SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186899SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196899SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206899SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216899SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226899SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236899SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246899SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256899SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266899SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276899SN/A */ 286899SN/A 296899SN/A#ifndef __DEV_IO_DEVICE_HH__ 306899SN/A#define __DEV_IO_DEVICE_HH__ 316899SN/A 326899SN/A#include "base/chunk_generator.hh" 336899SN/A#include "mem/port.hh" 346899SN/A#include "sim/eventq.hh" 356899SN/A#include "sim/sim_object.hh" 366899SN/A 376899SN/Aclass Platform; 386899SN/Aclass PioDevice; 396899SN/Aclass DmaDevice; 406899SN/A 416899SN/A/** 4211793Sbrandon.potter@amd.com * The PioPort class is a programmed i/o port that all devices that are 4311793Sbrandon.potter@amd.com * sensitive to an address range use. The port takes all the memory 4411800Sbrandon.potter@amd.com * access types and roles them into one read() and write() call that the device 457632SBrad.Beckmann@amd.com * must respond to. The device must also provide the addressRanges() function 468232Snate@binkert.org * with which it returns the address ranges it is interested in. An extra 476899SN/A * sendTiming() function is implemented which takes an delay. In this way the 486899SN/A * device can immediatly call sendTiming(pkt, time) after processing a request 497553SN/A * and the request will be handled by the port even if the port bus the device 507553SN/A * connects to is blocked. 517553SN/A */ 527553SN/Aclass PioPort : public Port 536899SN/A{ 547553SN/A protected: 556899SN/A /** The device that this port serves. */ 568851Sandreas.hansson@arm.com PioDevice *device; 578851Sandreas.hansson@arm.com 588851Sandreas.hansson@arm.com /** The platform that device/port are in. This is used to select which mode 598851Sandreas.hansson@arm.com * we are currently operating in. */ 608851Sandreas.hansson@arm.com Platform *platform; 618851Sandreas.hansson@arm.com 627053SN/A /** A list of outgoing timing response packets that haven't been serviced 637553SN/A * yet. */ 646899SN/A std::list<Packet*> transmitList; 656899SN/A 667553SN/A /** The current status of the peer(bus) that we are connected to. */ 676899SN/A Status peerStatus; 687053SN/A 697053SN/A virtual bool recvTiming(Packet &pkt); 706899SN/A 716899SN/A virtual Tick recvAtomic(Packet &pkt); 727053SN/A 737553SN/A virtual void recvFunctional(Packet &pkt) ; 746899SN/A 757053SN/A virtual void recvStatusChange(Status status) 767553SN/A { peerStatus = status; } 776899SN/A 786899SN/A virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner); 799294Sandreas.hansson@arm.com 809294Sandreas.hansson@arm.com /** 816899SN/A * This class is used to implemented sendTiming() with a delay. When a delay 826899SN/A * is requested a new event is created. When the event time expires it 838922Swilliam.wang@arm.com * attempts to send the packet. If it cannot, the packet is pushed onto the 848922Swilliam.wang@arm.com * transmit list to be sent when recvRetry() is called. */ 858922Swilliam.wang@arm.com class SendEvent : public Event 868922Swilliam.wang@arm.com { 878922Swilliam.wang@arm.com PioPort *port; 888922Swilliam.wang@arm.com Packet packet; 898922Swilliam.wang@arm.com 908922Swilliam.wang@arm.com SendEvent(PioPort *p, Packet &pkt, Tick t) 916899SN/A : Event(&mainEventQueue), packet(pkt) 926899SN/A { schedule(curTick + t); } 936899SN/A 946899SN/A virtual void process(); 958975Sandreas.hansson@arm.com 966899SN/A virtual const char *description() 978965Sandreas.hansson@arm.com { return "Future scheduled sendTiming event"; } 9811320Ssteve.reinhardt@amd.com 997553SN/A friend class PioPort; 1007553SN/A }; 1017553SN/A 1027053SN/A /** Schedule a sendTiming() event to be called in the future. */ 1037053SN/A void sendTiming(Packet &pkt, Tick time) 1047053SN/A { new PioPort::SendEvent(this, pkt, time); } 1056899SN/A 1066899SN/A /** This function pops the last element off the transmit list and sends it.*/ 1078922Swilliam.wang@arm.com virtual Packet *recvRetry(); 1087553SN/A 1096899SN/A public: 1107053SN/A PioPort(PioDevice *dev, Platform *p); 1116899SN/A 1127053SN/A friend class PioPort::SendEvent; 1136899SN/A}; 1146899SN/A 1157053SN/Aclass DmaPort : public Port 1167553SN/A{ 1176899SN/A protected: 1187553SN/A PioDevice *device; 1197553SN/A std::list<Packet*> transmitList; 1207553SN/A Event *completionEvent; 1217553SN/A 1226899SN/A 12311320Ssteve.reinhardt@amd.com virtual bool recvTiming(Packet &pkt); 1247823Ssteve.reinhardt@amd.com virtual Tick recvAtomic(Packet &pkt) 1256899SN/A { panic("dma port shouldn't be used for pio access."); } 1266899SN/A virtual void recvFunctional(Packet &pkt) 1277053SN/A { panic("dma port shouldn't be used for pio access."); } 1287553SN/A 1297053SN/A virtual void recvStatusChange(Status status) 1307553SN/A { ; } 1317553SN/A 1327823Ssteve.reinhardt@amd.com virtual Packet *recvRetry() ; 1337553SN/A 1347053SN/A virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner) 1357553SN/A { range_list.clear(); owner = true; } 1367053SN/A 1376899SN/A class SendEvent : public Event 1386899SN/A { 1397553SN/A DmaPort *port; 1407553SN/A Packet packet; 1416899SN/A 1427553SN/A SendEvent(PioPort *p, Packet &pkt, Tick t) 1436899SN/A : Event(&mainEventQueue), packet(pkt) 144 { schedule(curTick + t); } 145 146 virtual void process(); 147 148 virtual const char *description() 149 { return "Future scheduled sendTiming event"; } 150 151 friend class DmaPort; 152 }; 153 154 void dmaAction(Command cmd, DmaPort port, Addr addr, int size, 155 Event *event, uint8_t *data = NULL); 156 157 void sendDma(Packet &pkt); 158 159 public: 160 DmaPort(DmaDevice *dev); 161 162 friend class DmaPort::SendEvent; 163 164}; 165 166/** 167 * This device is the base class which all devices senstive to an address range 168 * inherit from. There are three pure virtual functions which all devices must 169 * implement addressRanges(), read(), and write(). The magic do choose which 170 * mode we are in, etc is handled by the PioPort so the device doesn't have to 171 * bother. 172 */ 173 174class PioDevice : public SimObject 175{ 176 protected: 177 178 /** The platform we are in. This is used to decide what type of memory 179 * transaction we should perform. */ 180 Platform *platform; 181 182 /** The pioPort that handles the requests for us and provides us requests 183 * that it sees. */ 184 PioPort *pioPort; 185 186 virtual void addressRanges(AddrRangeList &range_list, bool &owner) = 0; 187 188 /** As far as the devices are concerned they only accept atomic transactions 189 * which are converted to either a write or a read. */ 190 Tick recvAtomic(Packet &pkt) 191 { return pkt.cmd == Read ? this->read(pkt) : this->write(pkt); } 192 193 /** Pure virtual function that the device must implement. Called when a read 194 * command is recieved by the port. */ 195 virtual Tick read(Packet &pkt) = 0; 196 197 /** Pure virtual function that the device must implement. Called when a 198 * write command is recieved by the port. */ 199 virtual Tick write(Packet &pkt) = 0; 200 201 public: 202 /** Params struct which is extended through each device based on the 203 * parameters it needs. Since we are re-writing everything, we might as well 204 * start from the bottom this time. */ 205 206 struct Params 207 { 208 std::string name; 209 Platform *platform; 210 }; 211 protected: 212 Params *_params; 213 214 public: 215 const Params *params() const { return _params; } 216 217 PioDevice(Params *params) 218 : SimObject(params()->name), platform(params()->platform) 219 {} 220 221 virtual ~PioDevice(); 222 223 virtual Port *getPort(const std::string &if_name) 224 { 225 if (if_name == "pio") 226 if (pioPort != NULL) 227 panic("pio port already connected to."); 228 pioPort = new PioPort(this, params()->platform); 229 return pioPort; 230 else 231 return NULL; 232 } 233 friend class PioPort; 234 235}; 236 237class BasicPioDevice : public PioDevice 238{ 239 public: 240 struct Params 241 { 242 Addr pio_addr; 243 Tick pio_delay; 244 }; 245 246 protected: 247 /** Address that the device listens to. */ 248 Addr pioAddr; 249 250 /** Size that the device's address range. */ 251 Addr pioSize = 0; 252 253 /** Delay that the device experinces on an access. */ 254 Tick pioDelay; 255 256 public: 257 BasePioDevice(Params *p) 258 : PioDevice(p), pioAddr(p->pio_addr), pioDelay(p->pioDelay) 259 {} 260 261 virtual void addressRanges(AddrRangeList &range_list, bool &owner); 262}; 263 264class DmaDevice : public PioDevice 265{ 266 protected: 267 DmaPort *dmaPort; 268 269 public: 270 DmaDevice(const std::string &name, Platform *p); 271 virtual ~DmaDevice(); 272 273 virtual Port *getPort(const std::string &if_name) 274 { 275 if (if_name == "pio") 276 return pioPort; 277 else if (if_name == "dma") 278 return dmaPort; 279 else 280 return NULL; 281 } 282 283 friend class DmaPort; 284}; 285 286 287#endif // __DEV_IO_DEVICE_HH__ 288