tsunami_io.cc revision 772
112468Sglenn.bergmans@arm.com/* $Id$ */
212468Sglenn.bergmans@arm.com
312468Sglenn.bergmans@arm.com/* @file
412468Sglenn.bergmans@arm.com * Tsunami DMA fake
512468Sglenn.bergmans@arm.com */
612468Sglenn.bergmans@arm.com
712468Sglenn.bergmans@arm.com#include <deque>
812468Sglenn.bergmans@arm.com#include <string>
912468Sglenn.bergmans@arm.com#include <vector>
1012468Sglenn.bergmans@arm.com
1112468Sglenn.bergmans@arm.com#include "base/trace.hh"
1212468Sglenn.bergmans@arm.com#include "cpu/exec_context.hh"
1312468Sglenn.bergmans@arm.com#include "dev/console.hh"
1412468Sglenn.bergmans@arm.com#include "dev/etherdev.hh"
1512468Sglenn.bergmans@arm.com#include "dev/scsi_ctrl.hh"
1612468Sglenn.bergmans@arm.com#include "dev/tlaser_clock.hh"
1712468Sglenn.bergmans@arm.com#include "dev/tsunami_io.hh"
1812468Sglenn.bergmans@arm.com#include "dev/tsunamireg.h"
1912468Sglenn.bergmans@arm.com#include "dev/tsunami.hh"
2012468Sglenn.bergmans@arm.com#include "mem/functional_mem/memory_control.hh"
2112468Sglenn.bergmans@arm.com#include "sim/builder.hh"
2212468Sglenn.bergmans@arm.com#include "sim/system.hh"
2312468Sglenn.bergmans@arm.com
2412468Sglenn.bergmans@arm.comusing namespace std;
2512468Sglenn.bergmans@arm.comTsunamiIO::RTCEvent::RTCEvent()
2612468Sglenn.bergmans@arm.com    : Event(&mainEventQueue)
2712468Sglenn.bergmans@arm.com{
2812468Sglenn.bergmans@arm.com    DPRINTF(Tsunami, "RTC Event Initilizing\n");
2912468Sglenn.bergmans@arm.com    rtc_uip = 0;
3012468Sglenn.bergmans@arm.com    schedule(curTick + (curTick % ticksPerSecond));
3112468Sglenn.bergmans@arm.com}
3212468Sglenn.bergmans@arm.com
3312468Sglenn.bergmans@arm.comvoid
3412468Sglenn.bergmans@arm.comTsunamiIO::RTCEvent::process()
3512468Sglenn.bergmans@arm.com{
3612468Sglenn.bergmans@arm.com    DPRINTF(Tsunami, "Timer Interrupt\n");
3712468Sglenn.bergmans@arm.com    if (rtc_uip == 0) {
3812468Sglenn.bergmans@arm.com        rtc_uip = 1; //Signal a second has occured
3912468Sglenn.bergmans@arm.com        schedule(curTick + (curTick % ticksPerSecond) - 10);
4012468Sglenn.bergmans@arm.com            }
4112468Sglenn.bergmans@arm.com    else
4212468Sglenn.bergmans@arm.com        rtc_uip = 0; //Done signaling second has occured
4312468Sglenn.bergmans@arm.com        schedule(curTick + (curTick % ticksPerSecond));
4412468Sglenn.bergmans@arm.com}
4512468Sglenn.bergmans@arm.com
4612468Sglenn.bergmans@arm.comconst char *
4712468Sglenn.bergmans@arm.comTsunamiIO::RTCEvent::description()
4812468Sglenn.bergmans@arm.com{
4912468Sglenn.bergmans@arm.com    return "tsunami RTC changte second";
5012468Sglenn.bergmans@arm.com}
5112468Sglenn.bergmans@arm.com
5212468Sglenn.bergmans@arm.comuint8_t
5312468Sglenn.bergmans@arm.comTsunamiIO::RTCEvent::rtc_uip_value()
5412468Sglenn.bergmans@arm.com{
5512468Sglenn.bergmans@arm.com    return rtc_uip;
5612468Sglenn.bergmans@arm.com}
5712468Sglenn.bergmans@arm.com
5812468Sglenn.bergmans@arm.comTsunamiIO::ClockEvent::ClockEvent()
5912468Sglenn.bergmans@arm.com    : Event(&mainEventQueue)
6012468Sglenn.bergmans@arm.com{
6112468Sglenn.bergmans@arm.com    DPRINTF(Tsunami, "Clock Event Initilizing\n");
6212468Sglenn.bergmans@arm.com    mode = 0;
6312468Sglenn.bergmans@arm.com}
6412468Sglenn.bergmans@arm.com
6512468Sglenn.bergmans@arm.comvoid
6612468Sglenn.bergmans@arm.comTsunamiIO::ClockEvent::process()
6712468Sglenn.bergmans@arm.com{
6812468Sglenn.bergmans@arm.com    DPRINTF(Tsunami, "Timer Interrupt\n");
6912468Sglenn.bergmans@arm.com    if (mode == 0)
7012468Sglenn.bergmans@arm.com       status = 0x20; // set bit that linux is looking for
71    else
72        schedule(curTick + interval);
73}
74
75void
76TsunamiIO::ClockEvent::Program(int count)
77{
78    DPRINTF(Tsunami, "Timer set to curTick + %d\n", count);
79    interval = count * ticksPerSecond/1193180UL; // should be count * (cpufreq/pitfreq)
80    schedule(curTick + interval);
81    status = 0;
82}
83
84const char *
85TsunamiIO::ClockEvent::description()
86{
87    return "tsunami 8254 Interval timer";
88}
89
90void
91TsunamiIO::ClockEvent::ChangeMode(uint8_t md)
92{
93    mode = md;
94}
95
96uint8_t
97TsunamiIO::ClockEvent::Status()
98{
99    return status;
100}
101
102
103TsunamiIO::TsunamiIO(const string &name, /*Tsunami *t,*/
104                       Addr addr, Addr mask, MemoryController *mmu)
105    : MmapDevice(name, addr, mask, mmu)/*, tsunami(t) */
106{
107    timerData = 0;
108}
109
110Fault
111TsunamiIO::read(MemReqPtr req, uint8_t *data)
112{
113    DPRINTF(Tsunami, "io read  va=%#x size=%d IOPorrt=%#x\n",
114            req->vaddr, req->size, req->vaddr & 0xfff);
115
116    Addr daddr = (req->paddr & addr_mask);
117//    ExecContext *xc = req->xc;
118//    int cpuid = xc->cpu_id;
119
120    switch(req->size) {
121        case sizeof(uint8_t):
122            switch(daddr) {
123                case TSDEV_TMR_CTL:
124                    *(uint8_t*)data = timer2.Status();
125                    return No_Fault;
126                default:
127                    panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
128            }
129        case sizeof(uint16_t):
130        case sizeof(uint32_t):
131        case sizeof(uint64_t):
132        default:
133            panic("I/O Read - invalid size - va %#x size %d\n", req->vaddr, req->size);
134    }
135     panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
136
137    return No_Fault;
138}
139
140Fault
141TsunamiIO::write(MemReqPtr req, const uint8_t *data)
142{
143    DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x\n",
144            req->vaddr, req->size, req->vaddr & 0xfff);
145
146    Addr daddr = (req->paddr & addr_mask);
147
148    switch(req->size) {
149        case sizeof(uint8_t):
150            switch(daddr) {
151                case TSDEV_PIC1_MASK:
152                    mask1 = *(uint8_t*)data;
153                    return No_Fault;
154                case TSDEV_PIC2_MASK:
155                    mask2 = *(uint8_t*)data;
156                    return No_Fault;
157                case TSDEV_DMA1_RESET:
158                    return No_Fault;
159                case TSDEV_DMA2_RESET:
160                    return No_Fault;
161                case TSDEV_DMA1_MODE:
162                    mode1 = *(uint8_t*)data;
163                    return No_Fault;
164                case TSDEV_DMA2_MODE:
165                    mode2 = *(uint8_t*)data;
166                    return No_Fault;
167                case TSDEV_DMA1_MASK:
168                case TSDEV_DMA2_MASK:
169                    return No_Fault;
170                case TSDEV_TMR_CTL:
171                    return No_Fault;
172                case TSDEV_TMR2_CTL:
173                    if ((*(uint8_t*)data & 0x30) != 0x30)
174                        panic("Only L/M write supported\n");
175
176                    switch(*(uint8_t*)data >> 6) {
177                        case 0:
178                            timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
179                            break;
180                        case 1:
181                            timer1.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
182                            break;
183                        case 2:
184                            timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
185                            break;
186                        case 3:
187                        default:
188                            panic("Read Back Command not implemented\n");
189                    }
190                    return No_Fault;
191                case TSDEV_TMR2_DATA:
192                        /* two writes before we actually start the Timer
193                           so I set a flag in the timerData */
194                        if(timerData & 0x1000) {
195                            timerData &= 0x1000;
196                            timerData += *(uint8_t*)data << 8;
197                            timer2.Program(timerData);
198                        } else {
199                            timerData = *(uint8_t*)data;
200                            timerData |= 0x1000;
201                        }
202                        return No_Fault;
203                case TSDEV_TMR0_DATA:
204                        /* two writes before we actually start the Timer
205                           so I set a flag in the timerData */
206                        if(timerData & 0x1000) {
207                            timerData &= 0x1000;
208                            timerData += *(uint8_t*)data << 8;
209                            timer0.Program(timerData);
210                        } else {
211                            timerData = *(uint8_t*)data;
212                            timerData |= 0x1000;
213                        }
214                        return No_Fault;
215                 default:
216                    panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
217            }
218        case sizeof(uint16_t):
219        case sizeof(uint32_t):
220        case sizeof(uint64_t):
221        default:
222            panic("I/O Write - invalid size - va %#x size %d\n", req->vaddr, req->size);
223    }
224
225
226    return No_Fault;
227}
228
229void
230TsunamiIO::serialize(std::ostream &os)
231{
232    // code should be written
233}
234
235void
236TsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
237{
238    //code should be written
239}
240
241BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
242
243 //   SimObjectParam<Tsunami *> tsunami;
244    SimObjectParam<MemoryController *> mmu;
245    Param<Addr> addr;
246    Param<Addr> mask;
247
248END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
249
250BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
251
252//    INIT_PARAM(tsunami, "Tsunami"),
253    INIT_PARAM(mmu, "Memory Controller"),
254    INIT_PARAM(addr, "Device Address"),
255    INIT_PARAM(mask, "Address Mask")
256
257END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
258
259CREATE_SIM_OBJECT(TsunamiIO)
260{
261    return new TsunamiIO(getInstanceName(), /*tsunami,*/ addr, mask, mmu);
262}
263
264REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
265