tsunami_io.cc revision 772
1/* $Id$ */
2
3/* @file
4 * Tsunami DMA fake
5 */
6
7#include <deque>
8#include <string>
9#include <vector>
10
11#include "base/trace.hh"
12#include "cpu/exec_context.hh"
13#include "dev/console.hh"
14#include "dev/etherdev.hh"
15#include "dev/scsi_ctrl.hh"
16#include "dev/tlaser_clock.hh"
17#include "dev/tsunami_io.hh"
18#include "dev/tsunamireg.h"
19#include "dev/tsunami.hh"
20#include "mem/functional_mem/memory_control.hh"
21#include "sim/builder.hh"
22#include "sim/system.hh"
23
24using namespace std;
25TsunamiIO::RTCEvent::RTCEvent()
26    : Event(&mainEventQueue)
27{
28    DPRINTF(Tsunami, "RTC Event Initilizing\n");
29    rtc_uip = 0;
30    schedule(curTick + (curTick % ticksPerSecond));
31}
32
33void
34TsunamiIO::RTCEvent::process()
35{
36    DPRINTF(Tsunami, "Timer Interrupt\n");
37    if (rtc_uip == 0) {
38        rtc_uip = 1; //Signal a second has occured
39        schedule(curTick + (curTick % ticksPerSecond) - 10);
40            }
41    else
42        rtc_uip = 0; //Done signaling second has occured
43        schedule(curTick + (curTick % ticksPerSecond));
44}
45
46const char *
47TsunamiIO::RTCEvent::description()
48{
49    return "tsunami RTC changte second";
50}
51
52uint8_t
53TsunamiIO::RTCEvent::rtc_uip_value()
54{
55    return rtc_uip;
56}
57
58TsunamiIO::ClockEvent::ClockEvent()
59    : Event(&mainEventQueue)
60{
61    DPRINTF(Tsunami, "Clock Event Initilizing\n");
62    mode = 0;
63}
64
65void
66TsunamiIO::ClockEvent::process()
67{
68    DPRINTF(Tsunami, "Timer Interrupt\n");
69    if (mode == 0)
70       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