8 * Copyright (C) 1998 by the Board of Trustees
9 * of Leland Stanford Junior University.
10 * Copyright (C) 1998 Digital Equipment Corporation
12 * This file is part of the SimOS distribution.
13 * See LICENSE file for terms of the license.
20 #include "base/inifile.hh"
21 #include "base/str.hh" // for to_number
22 #include "base/trace.hh"
23 #include "dev/console.hh"
24 #include "dev/tsunami_uart.hh"
25 #include "mem/bus/bus.hh"
26 #include "mem/bus/pio_interface.hh"
27 #include "mem/bus/pio_interface_impl.hh"
28 #include "mem/functional_mem/memory_control.hh"
29 #include "sim/builder.hh"
30 #include "targetarch/ev5.hh"
34 #define CONS_INT_TX 0x01 // interrupt enable / state bits
35 #define CONS_INT_RX 0x02
38 TsunamiUart::IntrEvent::IntrEvent(TsunamiUart
*u
)
39 : Event(&mainEventQueue
), uart(u
)
41 DPRINTF(TsunamiUart
, "UART Interrupt Event Initilizing\n");
45 TsunamiUart::IntrEvent::description()
47 return "tsunami uart interrupt delay event";
51 TsunamiUart::IntrEvent::process()
53 if (UART_IER_THRI
& uart
->IER
) {
54 DPRINTF(TsunamiUart
, "UART InterEvent, interrupting\n");
55 uart
->cons
->raiseInt(CONS_INT_TX
);
58 DPRINTF(TsunamiUart
, "UART InterEvent, not interrupting\n");
63 TsunamiUart::IntrEvent::scheduleIntr()
65 DPRINTF(TsunamiUart
, "Scheduling IER interrupt\n");
67 schedule(curTick
+ 300);
69 reschedule(curTick
+ 300);
74 TsunamiUart::TsunamiUart(const string
&name
, SimConsole
*c
,
75 MemoryController
*mmu
, Addr a
,
76 HierParams
*hier
, Bus
*bus
)
77 : PioDevice(name
), addr(a
), cons(c
), status_store(0), valid_char(false),
80 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
83 pioInterface
= newPioInterface(name
, hier
, bus
, this,
84 &TsunamiUart::cacheAccess
);
85 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
92 TsunamiUart::read(MemReqPtr
&req
, uint8_t *data
)
94 Addr daddr
= req
->paddr
- (addr
& PA_IMPL_MASK
);
95 DPRINTF(TsunamiUart
, " read register %#x\n", daddr
);
98 case sizeof(uint64_t):
99 *(uint64_t *)data
= 0;
101 case sizeof(uint32_t):
102 *(uint32_t *)data
= 0;
104 case sizeof(uint16_t):
105 *(uint16_t *)data
= 0;
107 case sizeof(uint8_t):
108 *(uint8_t *)data
= 0;
114 case 0x5: // Status Register
116 int status
= cons
->intStatus();
118 valid_char
= cons
->in(next_char
);
120 status
&= ~CONS_INT_RX
;
122 status
|= CONS_INT_RX
;
125 if (status_store
== 3) {
126 // RR3 stuff? Don't really understand it, btw
128 if (status
& CONS_INT_TX
) {
131 } else if (status
& CONS_INT_RX
) {
135 DPRINTF(TsunamiUart
, "spurious read\n");
139 int reg
= (1 << 2) | (1 << 5) | (1 << 6);
140 if (status
& CONS_INT_RX
)
148 case 0x0: // Data register (RX)
149 DPRINTF(TsunamiUart
, "read data register \'%c\' %#02x\n",
150 isprint(next_char
) ? next_char
: ' ', next_char
);
156 case 0x1: // Interrupt Enable Register
157 // This is the lovely way linux checks there is actually a serial
158 // port at the desired address
161 else if (IER
== 0x0F)
167 // High two bits need to be clear for an 8250 (simple) serial port
168 // Low bit of IIR is 0 for a pending interrupt, 1 otherwise.
169 int status
= cons
->intStatus();
170 status
= (status
& 0x1) | (status
>> 1);
171 *data
= (~status
) & 0x1 ;
175 // panic("%s: read daddr=%#x type=read *data=%#x\n", name(), daddr, *data);
181 TsunamiUart::write(MemReqPtr
&req
, const uint8_t *data
)
183 Addr daddr
= req
->paddr
- (addr
& PA_IMPL_MASK
);
185 DPRINTF(TsunamiUart
, " write register %#x value %#x\n", daddr
, *(uint8_t*)data
);
189 status_store
= *data
;
191 case 0x03: // going to read RR3
194 case 0x28: // Ack of TX
196 if ((cons
->intStatus() & CONS_INT_TX
) == 0)
197 panic("Ack of transmit, though there was no interrupt");
199 cons
->clearInt(CONS_INT_TX
);
206 // going to write data???
210 DPRINTF(TsunamiUart
, "writing status register %#x \n",
215 case 0x0: // Data register (TX)
217 ourchar
= *(uint64_t *)data
;
218 if ((isprint(ourchar
) || iscntrl(ourchar
)) && (ourchar
!= 0x0C))
220 cons
->clearInt(CONS_INT_TX
);
221 intrEvent
.scheduleIntr();
225 IER
= *(uint8_t*)data
;
226 DPRINTF(TsunamiUart
, "writing to IER [%#x]\n", IER
);
227 if (UART_IER_THRI
& IER
)
228 cons
->raiseInt(CONS_INT_TX
);
230 cons
->clearInt(CONS_INT_TX
);
231 if (intrEvent
.scheduled())
232 intrEvent
.deschedule();
237 DPRINTF(TsunamiUart
, "writing to MCR %#x\n", *(uint8_t*)data
);
246 TsunamiUart::cacheAccess(MemReqPtr
&req
)
248 return curTick
+ 1000;
252 TsunamiUart::serialize(ostream
&os
)
254 SERIALIZE_SCALAR(status_store
);
255 SERIALIZE_SCALAR(next_char
);
256 SERIALIZE_SCALAR(valid_char
);
257 SERIALIZE_SCALAR(IER
);
261 TsunamiUart::unserialize(Checkpoint
*cp
, const std::string
§ion
)
263 UNSERIALIZE_SCALAR(status_store
);
264 UNSERIALIZE_SCALAR(next_char
);
265 UNSERIALIZE_SCALAR(valid_char
);
266 UNSERIALIZE_SCALAR(IER
);
269 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart
)
271 SimObjectParam
<SimConsole
*> console
;
272 SimObjectParam
<MemoryController
*> mmu
;
274 SimObjectParam
<Bus
*> io_bus
;
275 SimObjectParam
<HierParams
*> hier
;
278 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart
)
280 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiUart
)
282 INIT_PARAM(console
, "The console"),
283 INIT_PARAM(mmu
, "Memory Controller"),
284 INIT_PARAM(addr
, "Device Address"),
285 INIT_PARAM_DFLT(io_bus
, "The IO Bus to attach to", NULL
),
286 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
)
288 END_INIT_SIM_OBJECT_PARAMS(TsunamiUart
)
290 CREATE_SIM_OBJECT(TsunamiUart
)
292 return new TsunamiUart(getInstanceName(), console
, mmu
, addr
, hier
, io_bus
);
295 REGISTER_SIM_OBJECT("TsunamiUart", TsunamiUart
)