tsunami_io.cc revision 776
12292SN/A/* $Id$ */
22329SN/A
32292SN/A/* @file
42292SN/A * Tsunami I/O including PIC, PIT, RTC, DMA
52292SN/A */
62292SN/A
72292SN/A#include <sys/time.h>
82292SN/A
92292SN/A#include <deque>
102292SN/A#include <string>
112292SN/A#include <vector>
122292SN/A
132292SN/A#include "base/trace.hh"
142292SN/A#include "cpu/exec_context.hh"
152292SN/A#include "dev/console.hh"
162292SN/A#include "dev/tlaser_clock.hh"
172292SN/A#include "dev/tsunami_io.hh"
182292SN/A#include "dev/tsunamireg.h"
192292SN/A#include "dev/tsunami.hh"
202292SN/A#include "mem/functional_mem/memory_control.hh"
212292SN/A#include "sim/builder.hh"
222292SN/A#include "dev/tsunami_cchip.hh"
232292SN/A
242292SN/Ausing namespace std;
252292SN/A
262292SN/A#define UNIX_YEAR_OFFSET 52
272689Sktlim@umich.edu
282689Sktlim@umich.edu
292689Sktlim@umich.edu// Timer Event for Periodic interrupt of RTC
302292SN/ATsunamiIO::RTCEvent::RTCEvent(Tsunami* t)
312292SN/A    : Event(&mainEventQueue), tsunami(t)
322292SN/A{
332292SN/A    DPRINTF(MC146818, "RTC Event Initilizing\n");
342292SN/A    schedule(curTick + ticksPerSecond/RTC_RATE);
352329SN/A}
362292SN/A
372292SN/Avoid
382292SN/ATsunamiIO::RTCEvent::process()
392329SN/A{
402292SN/A    DPRINTF(MC146818, "RTC Timer Interrupt\n");
412292SN/A    schedule(curTick + ticksPerSecond/RTC_RATE);
422292SN/A    //Actually interrupt the processor here
432808Ssaidi@eecs.umich.edu    if (!tsunami->cchip->RTCInterrupting) {
442669Sktlim@umich.edu        tsunami->cchip->misc |= 1 << 7;
452292SN/A        tsunami->cchip->RTCInterrupting = true;
462292SN/A        tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ2, 0);
472329SN/A    }
482329SN/A}
492329SN/A
502329SN/Aconst char *
512329SN/ATsunamiIO::RTCEvent::description()
522329SN/A{
532329SN/A    return "tsunami RTC 1024Hz interrupt";
542329SN/A}
552329SN/A
562329SN/A// Timer Event for PIT Timers
572292SN/ATsunamiIO::ClockEvent::ClockEvent()
582292SN/A    : Event(&mainEventQueue)
592292SN/A{
602292SN/A    DPRINTF(Tsunami, "Clock Event Initilizing\n");
612292SN/A    mode = 0;
622292SN/A}
632292SN/A
642733Sktlim@umich.eduvoid
652292SN/ATsunamiIO::ClockEvent::process()
662292SN/A{
672907Sktlim@umich.edu    DPRINTF(Tsunami, "Timer Interrupt\n");
682292SN/A    if (mode == 0)
692292SN/A       status = 0x20; // set bit that linux is looking for
702292SN/A    else
712292SN/A        schedule(curTick + interval);
722292SN/A}
732292SN/A
742292SN/Avoid
752907Sktlim@umich.eduTsunamiIO::ClockEvent::Program(int count)
762292SN/A{
772292SN/A    DPRINTF(Tsunami, "Timer set to curTick + %d\n", count);
782292SN/A    // should be count * (cpufreq/pitfreq)
792292SN/A    interval = count * ticksPerSecond/1193180UL;
802292SN/A    schedule(curTick + interval);
812727Sktlim@umich.edu    status = 0;
822727Sktlim@umich.edu}
832727Sktlim@umich.edu
842292SN/Aconst char *
852733Sktlim@umich.eduTsunamiIO::ClockEvent::description()
862292SN/A{
872292SN/A    return "tsunami 8254 Interval timer";
882292SN/A}
892292SN/A
902292SN/Avoid
912907Sktlim@umich.eduTsunamiIO::ClockEvent::ChangeMode(uint8_t md)
922907Sktlim@umich.edu{
932907Sktlim@umich.edu    mode = md;
942907Sktlim@umich.edu}
952348SN/A
962307SN/Auint8_t
972307SN/ATsunamiIO::ClockEvent::Status()
982348SN/A{
992307SN/A    return status;
1002307SN/A}
1012348SN/A
1022307SN/A
1032307SN/A
1042292SN/A
1052292SN/ATsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
1062292SN/A                       Addr addr, Addr mask, MemoryController *mmu)
1072292SN/A    : MmapDevice(name, addr, mask, mmu), tsunami(t), rtc(t)
1082292SN/A{
1092292SN/A    timerData = 0;
1102292SN/A    set_time(init_time == 0 ? time(NULL) : init_time);
1112292SN/A    uip = 1;
1122292SN/A}
1132292SN/A
1142292SN/Avoid
1152292SN/ATsunamiIO::set_time(time_t t)
1162292SN/A{
1172292SN/A    gmtime_r(&t, &tm);
1182292SN/A    DPRINTFN("Real-time clock set to %s", asctime(&tm));
1192292SN/A}
1202292SN/A
1212329SN/AFault
1222292SN/ATsunamiIO::read(MemReqPtr req, uint8_t *data)
1232292SN/A{
1242292SN/A    DPRINTF(Tsunami, "io read  va=%#x size=%d IOPorrt=%#x\n",
1252292SN/A            req->vaddr, req->size, req->vaddr & 0xfff);
1262292SN/A
1272292SN/A    Addr daddr = (req->paddr & addr_mask);
1282292SN/A//    ExecContext *xc = req->xc;
1292292SN/A//    int cpuid = xc->cpu_id;
1302292SN/A
1312292SN/A    switch(req->size) {
1322292SN/A        case sizeof(uint8_t):
1332292SN/A            switch(daddr) {
1342292SN/A                case TSDEV_TMR_CTL:
1352292SN/A                    *(uint8_t*)data = timer2.Status();
1362790Sktlim@umich.edu                    return No_Fault;
1372790Sktlim@umich.edu                case TSDEV_RTC_DATA:
1382669Sktlim@umich.edu                    switch(RTCAddress) {
1392669Sktlim@umich.edu                        case RTC_CONTROL_REGISTERA:
1402292SN/A                            *(uint8_t*)data = uip << 7 | 0x26;
1412292SN/A                            uip = !uip;
1422292SN/A                            return No_Fault;
1432292SN/A                        case RTC_CONTROL_REGISTERB:
1442292SN/A                            // DM and 24/12 and UIE
1452292SN/A                            *(uint8_t*)data = 0x46;
1462292SN/A                            return No_Fault;
1472292SN/A                        case RTC_CONTROL_REGISTERC:
1482292SN/A                            // If we want to support RTC user access in linux
1492292SN/A                            // This won't work, but for now it's fine
1502292SN/A                            *(uint8_t*)data = 0x00;
1512292SN/A                            return No_Fault;
1522292SN/A                        case RTC_CONTROL_REGISTERD:
1532292SN/A                            panic("RTC Control Register D not implemented");
1542292SN/A                        case RTC_SECOND:
1552292SN/A                            *(uint8_t *)data = tm.tm_sec;
1562292SN/A                            return No_Fault;
1572292SN/A                        case RTC_MINUTE:
1582292SN/A                            *(uint8_t *)data = tm.tm_min;
1592292SN/A                            return No_Fault;
1602292SN/A                        case RTC_HOUR:
1612292SN/A                            *(uint8_t *)data = tm.tm_hour;
1622292SN/A                            return No_Fault;
1632329SN/A                        case RTC_DAY_OF_WEEK:
1642292SN/A                            *(uint8_t *)data = tm.tm_wday;
1652292SN/A                            return No_Fault;
1662292SN/A                        case RTC_DAY_OF_MONTH:
1672348SN/A                            *(uint8_t *)data = tm.tm_mday;
1682292SN/A                        case RTC_MONTH:
1692292SN/A                            *(uint8_t *)data = tm.tm_mon + 1;
1702292SN/A                            return No_Fault;
1712348SN/A                        case RTC_YEAR:
1722292SN/A                            *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET;
1732292SN/A                            return No_Fault;
1742292SN/A                        default:
1752348SN/A                            panic("Unknown RTC Address\n");
1762292SN/A                    }
1772292SN/A
1782292SN/A                default:
1792292SN/A                    panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
1802292SN/A            }
1812292SN/A        case sizeof(uint16_t):
1822292SN/A        case sizeof(uint32_t):
1832292SN/A        case sizeof(uint64_t):
1842292SN/A        default:
1852292SN/A            panic("I/O Read - invalid size - va %#x size %d\n", req->vaddr, req->size);
1862292SN/A    }
1872292SN/A     panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
1882292SN/A
1892292SN/A    return No_Fault;
1902292SN/A}
1912292SN/A
1922292SN/AFault
1932292SN/ATsunamiIO::write(MemReqPtr req, const uint8_t *data)
1942292SN/A{
1952292SN/A    DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x\n",
1962292SN/A            req->vaddr, req->size, req->vaddr & 0xfff);
1972292SN/A
1982292SN/A    Addr daddr = (req->paddr & addr_mask);
1992292SN/A
2002292SN/A    switch(req->size) {
2012292SN/A        case sizeof(uint8_t):
2022292SN/A            switch(daddr) {
2032292SN/A                case TSDEV_PIC1_MASK:
2042292SN/A                    mask1 = *(uint8_t*)data;
2052292SN/A                    return No_Fault;
2062292SN/A                case TSDEV_PIC2_MASK:
2072292SN/A                    mask2 = *(uint8_t*)data;
2082292SN/A                    return No_Fault;
2092292SN/A                case TSDEV_DMA1_RESET:
2102292SN/A                    return No_Fault;
2112678Sktlim@umich.edu                case TSDEV_DMA2_RESET:
2122678Sktlim@umich.edu                    return No_Fault;
2132292SN/A                case TSDEV_DMA1_MODE:
2142907Sktlim@umich.edu                    mode1 = *(uint8_t*)data;
2152907Sktlim@umich.edu                    return No_Fault;
2162907Sktlim@umich.edu                case TSDEV_DMA2_MODE:
2172292SN/A                    mode2 = *(uint8_t*)data;
2182698Sktlim@umich.edu                    return No_Fault;
2192678Sktlim@umich.edu                case TSDEV_DMA1_MASK:
2202678Sktlim@umich.edu                case TSDEV_DMA2_MASK:
2212698Sktlim@umich.edu                    return No_Fault;
2222693Sktlim@umich.edu                case TSDEV_TMR_CTL:
2232693Sktlim@umich.edu                    return No_Fault;
2242292SN/A                case TSDEV_TMR2_CTL:
2252292SN/A                    if ((*(uint8_t*)data & 0x30) != 0x30)
2262292SN/A                        panic("Only L/M write supported\n");
2272292SN/A
2282292SN/A                    switch(*(uint8_t*)data >> 6) {
2292292SN/A                        case 0:
2302292SN/A                            timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
2312292SN/A                            break;
2322292SN/A                        case 2:
2332292SN/A                            timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
2342292SN/A                            break;
2352292SN/A                        default:
2362329SN/A                            panic("Read Back Command not implemented\n");
2372329SN/A                    }
2382329SN/A                    return No_Fault;
2392329SN/A                case TSDEV_TMR2_DATA:
2402292SN/A                        /* two writes before we actually start the Timer
2412292SN/A                           so I set a flag in the timerData */
2422733Sktlim@umich.edu                        if(timerData & 0x1000) {
2432292SN/A                            timerData &= 0x1000;
2442292SN/A                            timerData += *(uint8_t*)data << 8;
2452292SN/A                            timer2.Program(timerData);
2462292SN/A                        } else {
2472907Sktlim@umich.edu                            timerData = *(uint8_t*)data;
2482907Sktlim@umich.edu                            timerData |= 0x1000;
2492669Sktlim@umich.edu                        }
2502907Sktlim@umich.edu                        return No_Fault;
2512907Sktlim@umich.edu                case TSDEV_TMR0_DATA:
2522292SN/A                        /* two writes before we actually start the Timer
2532698Sktlim@umich.edu                           so I set a flag in the timerData */
2542678Sktlim@umich.edu                        if(timerData & 0x1000) {
2552678Sktlim@umich.edu                            timerData &= 0x1000;
2562678Sktlim@umich.edu                            timerData += *(uint8_t*)data << 8;
2572698Sktlim@umich.edu                            timer0.Program(timerData);
2582678Sktlim@umich.edu                        } else {
2592678Sktlim@umich.edu                            timerData = *(uint8_t*)data;
2602678Sktlim@umich.edu                            timerData |= 0x1000;
2612678Sktlim@umich.edu                        }
2622698Sktlim@umich.edu                        return No_Fault;
2632678Sktlim@umich.edu                case TSDEV_RTC_ADDR:
2642698Sktlim@umich.edu                        RTCAddress = *(uint8_t*)data;
2652678Sktlim@umich.edu                        return No_Fault;
2662698Sktlim@umich.edu                case TSDEV_RTC_DATA:
2672678Sktlim@umich.edu                        panic("RTC Write not implmented (rtc.o won't work)\n");
2682698Sktlim@umich.edu                 default:
2692678Sktlim@umich.edu                    panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
2702678Sktlim@umich.edu            }
2712678Sktlim@umich.edu        case sizeof(uint16_t):
2722698Sktlim@umich.edu        case sizeof(uint32_t):
2732678Sktlim@umich.edu        case sizeof(uint64_t):
2742678Sktlim@umich.edu        default:
2752678Sktlim@umich.edu            panic("I/O Write - invalid size - va %#x size %d\n", req->vaddr, req->size);
2762678Sktlim@umich.edu    }
2772678Sktlim@umich.edu
2782678Sktlim@umich.edu
2792678Sktlim@umich.edu    return No_Fault;
2802678Sktlim@umich.edu}
2812678Sktlim@umich.edu
2822678Sktlim@umich.eduvoid
2832678Sktlim@umich.eduTsunamiIO::serialize(std::ostream &os)
2842678Sktlim@umich.edu{
2852698Sktlim@umich.edu    // code should be written
2862678Sktlim@umich.edu}
2872678Sktlim@umich.edu
2882698Sktlim@umich.eduvoid
2892678Sktlim@umich.eduTsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
2902678Sktlim@umich.edu{
2912678Sktlim@umich.edu    //code should be written
2922678Sktlim@umich.edu}
2932678Sktlim@umich.edu
2942678Sktlim@umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
2952292SN/A
2962292SN/A    SimObjectParam<Tsunami *> tsunami;
2972292SN/A    Param<time_t> time;
2982292SN/A    SimObjectParam<MemoryController *> mmu;
2992292SN/A    Param<Addr> addr;
3002292SN/A    Param<Addr> mask;
3012292SN/A
3022292SN/AEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
3032292SN/A
3042292SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
3052292SN/A
3062292SN/A    INIT_PARAM(tsunami, "Tsunami"),
3072292SN/A    INIT_PARAM_DFLT(time, "System time to use "
3082292SN/A            "(0 for actual time, default is 1/1/06", ULL(1136073600)),
3092292SN/A    INIT_PARAM(mmu, "Memory Controller"),
3102292SN/A    INIT_PARAM(addr, "Device Address"),
3112669Sktlim@umich.edu    INIT_PARAM(mask, "Address Mask")
3122669Sktlim@umich.edu
3132292SN/AEND_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
3142292SN/A
3152292SN/ACREATE_SIM_OBJECT(TsunamiIO)
3162292SN/A{
3172292SN/A    return new TsunamiIO(getInstanceName(), tsunami, time,  addr,
3182292SN/A                         mask, mmu);
3192292SN/A}
3202292SN/A
3212292SN/AREGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
3222292SN/A