tsunami_io.cc revision 772
12SN/A/* $Id$ */
22190SN/A
32SN/A/* @file
42SN/A * Tsunami DMA fake
52SN/A */
62SN/A
72SN/A#include <deque>
82SN/A#include <string>
92SN/A#include <vector>
102SN/A
112SN/A#include "base/trace.hh"
122SN/A#include "cpu/exec_context.hh"
132SN/A#include "dev/console.hh"
142SN/A#include "dev/etherdev.hh"
152SN/A#include "dev/scsi_ctrl.hh"
162SN/A#include "dev/tlaser_clock.hh"
172SN/A#include "dev/tsunami_io.hh"
182SN/A#include "dev/tsunamireg.h"
192SN/A#include "dev/tsunami.hh"
202SN/A#include "mem/functional_mem/memory_control.hh"
212SN/A#include "sim/builder.hh"
222SN/A#include "sim/system.hh"
232SN/A
242SN/Ausing namespace std;
252SN/ATsunamiIO::RTCEvent::RTCEvent()
262SN/A    : Event(&mainEventQueue)
272665SN/A{
282665SN/A    DPRINTF(Tsunami, "RTC Event Initilizing\n");
292SN/A    rtc_uip = 0;
302SN/A    schedule(curTick + (curTick % ticksPerSecond));
312680Sktlim@umich.edu}
322680Sktlim@umich.edu
332SN/Avoid
342972Sgblack@eecs.umich.eduTsunamiIO::RTCEvent::process()
353453Sgblack@eecs.umich.edu{
361858SN/A    DPRINTF(Tsunami, "Timer Interrupt\n");
372423SN/A    if (rtc_uip == 0) {
382190SN/A        rtc_uip = 1; //Signal a second has occured
3956SN/A        schedule(curTick + (curTick % ticksPerSecond) - 10);
40217SN/A            }
412036SN/A    else
422SN/A        rtc_uip = 0; //Done signaling second has occured
432190SN/A        schedule(curTick + (curTick % ticksPerSecond));
442190SN/A}
453453Sgblack@eecs.umich.edu
463453Sgblack@eecs.umich.educonst char *
476022Sgblack@eecs.umich.eduTsunamiIO::RTCEvent::description()
483453Sgblack@eecs.umich.edu{
492190SN/A    return "tsunami RTC changte second";
502313SN/A}
512235SN/A
522423SN/Auint8_t
532521SN/ATsunamiIO::RTCEvent::rtc_uip_value()
542521SN/A{
552190SN/A    return rtc_uip;
562190SN/A}
573548Sgblack@eecs.umich.edu
583548Sgblack@eecs.umich.eduTsunamiIO::ClockEvent::ClockEvent()
593548Sgblack@eecs.umich.edu    : Event(&mainEventQueue)
603548Sgblack@eecs.umich.edu{
612330SN/A    DPRINTF(Tsunami, "Clock Event Initilizing\n");
622SN/A    mode = 0;
632680Sktlim@umich.edu}
642680Sktlim@umich.edu
652680Sktlim@umich.eduvoid
662680Sktlim@umich.eduTsunamiIO::ClockEvent::process()
672680Sktlim@umich.edu{
682680Sktlim@umich.edu    DPRINTF(Tsunami, "Timer Interrupt\n");
692680Sktlim@umich.edu    if (mode == 0)
702680Sktlim@umich.edu       status = 0x20; // set bit that linux is looking for
712680Sktlim@umich.edu    else
722680Sktlim@umich.edu        schedule(curTick + interval);
732680Sktlim@umich.edu}
742682Sktlim@umich.edu
752680Sktlim@umich.eduvoid
762680Sktlim@umich.eduTsunamiIO::ClockEvent::Program(int count)
772680Sktlim@umich.edu{
782680Sktlim@umich.edu    DPRINTF(Tsunami, "Timer set to curTick + %d\n", count);
792680Sktlim@umich.edu    interval = count * ticksPerSecond/1193180UL; // should be count * (cpufreq/pitfreq)
802SN/A    schedule(curTick + interval);
812107SN/A    status = 0;
822107SN/A}
832107SN/A
842190SN/Aconst char *
852455SN/ATsunamiIO::ClockEvent::description()
862455SN/A{
872107SN/A    return "tsunami 8254 Interval timer";
882159SN/A}
892SN/A
906029Ssteve.reinhardt@amd.comvoid
91246SN/ATsunamiIO::ClockEvent::ChangeMode(uint8_t md)
92246SN/A{
93246SN/A    mode = md;
94246SN/A}
95246SN/A
96246SN/Auint8_t
97246SN/ATsunamiIO::ClockEvent::Status()
982190SN/A{
99246SN/A    return status;
100246SN/A}
101246SN/A
102246SN/A
103246SN/ATsunamiIO::TsunamiIO(const string &name, /*Tsunami *t,*/
104246SN/A                       Addr addr, Addr mask, MemoryController *mmu)
105246SN/A    : MmapDevice(name, addr, mask, mmu)/*, tsunami(t) */
1062SN/A{
1072680Sktlim@umich.edu    timerData = 0;
1082423SN/A}
1092190SN/A
110180SN/AFault
1115712Shsul@eecs.umich.eduTsunamiIO::read(MemReqPtr req, uint8_t *data)
1122190SN/A{
1135715Shsul@eecs.umich.edu    DPRINTF(Tsunami, "io read  va=%#x size=%d IOPorrt=%#x\n",
1145715Shsul@eecs.umich.edu            req->vaddr, req->size, req->vaddr & 0xfff);
1155715Shsul@eecs.umich.edu
1165714Shsul@eecs.umich.edu    Addr daddr = (req->paddr & addr_mask);
1175714Shsul@eecs.umich.edu//    ExecContext *xc = req->xc;
1185714Shsul@eecs.umich.edu//    int cpuid = xc->cpu_id;
1195714Shsul@eecs.umich.edu
1205714Shsul@eecs.umich.edu    switch(req->size) {
1216022Sgblack@eecs.umich.edu        case sizeof(uint8_t):
1222190SN/A            switch(daddr) {
1236022Sgblack@eecs.umich.edu                case TSDEV_TMR_CTL:
1242521SN/A                    *(uint8_t*)data = timer2.Status();
1254997Sgblack@eecs.umich.edu                    return No_Fault;
1264997Sgblack@eecs.umich.edu                default:
1275803Snate@binkert.org                    panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
1283548Sgblack@eecs.umich.edu            }
1292654SN/A        case sizeof(uint16_t):
1302521SN/A        case sizeof(uint32_t):
1312521SN/A        case sizeof(uint64_t):
1325499Ssaidi@eecs.umich.edu        default:
1333673Srdreslin@umich.edu            panic("I/O Read - invalid size - va %#x size %d\n", req->vaddr, req->size);
1345497Ssaidi@eecs.umich.edu    }
1352190SN/A     panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
1362518SN/A
1372518SN/A    return No_Fault;
1382190SN/A}
1392190SN/A
1402190SN/AFault
1412190SN/ATsunamiIO::write(MemReqPtr req, const uint8_t *data)
1422159SN/A{
1432235SN/A    DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x\n",
1442103SN/A            req->vaddr, req->size, req->vaddr & 0xfff);
145393SN/A
146393SN/A    Addr daddr = (req->paddr & addr_mask);
1472190SN/A
148393SN/A    switch(req->size) {
149393SN/A        case sizeof(uint8_t):
1505250Sksewell@umich.edu            switch(daddr) {
151393SN/A                case TSDEV_PIC1_MASK:
152393SN/A                    mask1 = *(uint8_t*)data;
1535250Sksewell@umich.edu                    return No_Fault;
1542159SN/A                case TSDEV_PIC2_MASK:
1552159SN/A                    mask2 = *(uint8_t*)data;
1562190SN/A                    return No_Fault;
1572159SN/A                case TSDEV_DMA1_RESET:
1582159SN/A                    return No_Fault;
1592680Sktlim@umich.edu                case TSDEV_DMA2_RESET:
1602159SN/A                    return No_Fault;
1612190SN/A                case TSDEV_DMA1_MODE:
1622159SN/A                    mode1 = *(uint8_t*)data;
1632190SN/A                    return No_Fault;
1642190SN/A                case TSDEV_DMA2_MODE:
1652159SN/A                    mode2 = *(uint8_t*)data;
1662235SN/A                    return No_Fault;
1672313SN/A                case TSDEV_DMA1_MASK:
1682235SN/A                case TSDEV_DMA2_MASK:
1692235SN/A                    return No_Fault;
1702235SN/A                case TSDEV_TMR_CTL:
1712235SN/A                    return No_Fault;
1722235SN/A                case TSDEV_TMR2_CTL:
1732254SN/A                    if ((*(uint8_t*)data & 0x30) != 0x30)
1742254SN/A                        panic("Only L/M write supported\n");
1752254SN/A
1762235SN/A                    switch(*(uint8_t*)data >> 6) {
1772235SN/A                        case 0:
1782235SN/A                            timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
1792254SN/A                            break;
1802190SN/A                        case 1:
1812159SN/A                            timer1.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
1822680Sktlim@umich.edu                            break;
1832159SN/A                        case 2:
1842190SN/A                            timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
1852159SN/A                            break;
1862159SN/A                        case 3:
1872159SN/A                        default:
1882159SN/A                            panic("Read Back Command not implemented\n");
1892190SN/A                    }
1902159SN/A                    return No_Fault;
1912455SN/A                case TSDEV_TMR2_DATA:
1922159SN/A                        /* two writes before we actually start the Timer
1932455SN/A                           so I set a flag in the timerData */
1942159SN/A                        if(timerData & 0x1000) {
1952455SN/A                            timerData &= 0x1000;
1962455SN/A                            timerData += *(uint8_t*)data << 8;
1972455SN/A                            timer2.Program(timerData);
1982159SN/A                        } else {
1992190SN/A                            timerData = *(uint8_t*)data;
2002159SN/A                            timerData |= 0x1000;
2012455SN/A                        }
2022159SN/A                        return No_Fault;
2032455SN/A                case TSDEV_TMR0_DATA:
2042159SN/A                        /* two writes before we actually start the Timer
2052455SN/A                           so I set a flag in the timerData */
2062455SN/A                        if(timerData & 0x1000) {
2072455SN/A                            timerData &= 0x1000;
2082159SN/A                            timerData += *(uint8_t*)data << 8;
2092190SN/A                            timer0.Program(timerData);
2102159SN/A                        } else {
2112190SN/A                            timerData = *(uint8_t*)data;
2122159SN/A                            timerData |= 0x1000;
2132190SN/A                        }
2142159SN/A                        return No_Fault;
2152190SN/A                 default:
2162159SN/A                    panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
2172447SN/A            }
2182447SN/A        case sizeof(uint16_t):
2192447SN/A        case sizeof(uint32_t):
2202447SN/A        case sizeof(uint64_t):
2215260Sksewell@umich.edu        default:
2225260Sksewell@umich.edu            panic("I/O Write - invalid size - va %#x size %d\n", req->vaddr, req->size);
2235260Sksewell@umich.edu    }
2245260Sksewell@umich.edu
2255260Sksewell@umich.edu
2265260Sksewell@umich.edu    return No_Fault;
2275260Sksewell@umich.edu}
2285260Sksewell@umich.edu
2294172Ssaidi@eecs.umich.eduvoid
2304172Ssaidi@eecs.umich.eduTsunamiIO::serialize(std::ostream &os)
2312190SN/A{
2322159SN/A    // code should be written
2334172Ssaidi@eecs.umich.edu}
2342190SN/A
2353468Sgblack@eecs.umich.eduvoid
2362190SN/ATsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
2374661Sksewell@umich.edu{
2384661Sksewell@umich.edu    //code should be written
2394661Sksewell@umich.edu}
2404661Sksewell@umich.edu
2412235SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
2422235SN/A
2432190SN/A //   SimObjectParam<Tsunami *> tsunami;
2442190SN/A    SimObjectParam<MemoryController *> mmu;
2452190SN/A    Param<Addr> addr;
2462159SN/A    Param<Addr> mask;
2472235SN/A
2482190SN/AEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
2492190SN/A
2502159SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
2512235SN/A
2522190SN/A//    INIT_PARAM(tsunami, "Tsunami"),
2532834Sksewell@umich.edu    INIT_PARAM(mmu, "Memory Controller"),
2544111Sgblack@eecs.umich.edu    INIT_PARAM(addr, "Device Address"),
2554111Sgblack@eecs.umich.edu    INIT_PARAM(mask, "Address Mask")
2562834Sksewell@umich.edu
2572834Sksewell@umich.eduEND_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
2582834Sksewell@umich.edu
2592834Sksewell@umich.eduCREATE_SIM_OBJECT(TsunamiIO)
2602159SN/A{
2612525SN/A    return new TsunamiIO(getInstanceName(), /*tsunami,*/ addr, mask, mmu);
2625217Ssaidi@eecs.umich.edu}
2635217Ssaidi@eecs.umich.edu
2642159SN/AREGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
2652159SN/A