X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fuart8250.cc;h=2bbcf2683bb8093e0a0c5457110ed4a3e33a9dbc;hb=d4e83a400189ef91a5b0f444c9c99d443cc1a251;hp=b92527b5a95299c48faf942bb352046be12574a2;hpb=15a8f050605919579e81b6abb98a0b596334216d;p=gem5.git diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index b92527b5a..2bbcf2683 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -35,29 +35,30 @@ #include #include -#include "arch/alpha/ev5.hh" #include "base/inifile.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" -#include "dev/simconsole.hh" -#include "dev/uart8250.hh" +#include "config/the_isa.hh" #include "dev/platform.hh" -#include "sim/builder.hh" +#include "dev/terminal.hh" +#include "dev/uart8250.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" using namespace std; using namespace TheISA; Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit) - : Event(&mainEventQueue), uart(u) + : uart(u) { DPRINTF(Uart, "UART Interrupt Event Initilizing\n"); intrBit = bit; } const char * -Uart8250::IntrEvent::description() +Uart8250::IntrEvent::description() const { - return "uart interrupt delay event"; + return "uart interrupt delay"; } void @@ -67,6 +68,7 @@ Uart8250::IntrEvent::process() DPRINTF(Uart, "UART InterEvent, interrupting\n"); uart->platform->postConsoleInt(); uart->status |= intrBit; + uart->lastTxInt = curTick; } else DPRINTF(Uart, "UART InterEvent, not interrupting\n"); @@ -88,31 +90,26 @@ Uart8250::IntrEvent::process() void Uart8250::IntrEvent::scheduleIntr() { - static const Tick interval = (Tick)((Clock::Float::s / 2e9) * 450); + static const Tick interval = 225 * SimClock::Int::ns; DPRINTF(Uart, "Scheduling IER interrupt for %#x, at cycle %lld\n", intrBit, curTick + interval); if (!scheduled()) - schedule(curTick + interval); + uart->schedule(this, curTick + interval); else - reschedule(curTick + interval); + uart->reschedule(this, curTick + interval); } -Uart8250::Uart8250(Params *p) - : Uart(p), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT) +Uart8250::Uart8250(const Params *p) + : Uart(p), IER(0), DLAB(0), LCR(0), MCR(0), lastTxInt(0), + txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT) { pioSize = 8; - - IER = 0; - DLAB = 0; - LCR = 0; - MCR = 0; } Tick -Uart8250::read(Packet *pkt) +Uart8250::read(PacketPtr pkt) { - assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getSize() == 1); @@ -124,8 +121,8 @@ Uart8250::read(Packet *pkt) switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // read byte - if (cons->dataAvailable()) - pkt->set(cons->in()); + if (term->dataAvailable()) + pkt->set(term->in()); else { pkt->set((uint8_t)0); // A limited amount of these are ok. @@ -134,7 +131,7 @@ Uart8250::read(Packet *pkt) status &= ~RX_INT; platform->clearConsoleInt(); - if (cons->dataAvailable() && (IER & UART_IER_RDI)) + if (term->dataAvailable() && (IER & UART_IER_RDI)) rxIntrEvent.scheduleIntr(); } else { // dll divisor latch ; @@ -152,13 +149,13 @@ Uart8250::read(Packet *pkt) if (status & RX_INT) /* Rx data interrupt has a higher priority */ pkt->set(IIR_RXID); - else if (status & TX_INT) + else if (status & TX_INT) { pkt->set(IIR_TXID); - else + //Tx interrupts are cleared on IIR reads + status &= ~TX_INT; + } else pkt->set(IIR_NOPEND); - //Tx interrupts are cleared on IIR reads - status &= ~TX_INT; break; case 0x3: // Line Control Register (LCR) pkt->set(LCR); @@ -169,7 +166,7 @@ Uart8250::read(Packet *pkt) uint8_t lsr; lsr = 0; // check if there are any bytes to be read - if (cons->dataAvailable()) + if (term->dataAvailable()) lsr = UART_LSR_DR; lsr |= UART_LSR_TEMT | UART_LSR_THRE; pkt->set(lsr); @@ -187,15 +184,14 @@ Uart8250::read(Packet *pkt) /* uint32_t d32 = *data; DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32); */ - pkt->result = Packet::Success; + pkt->makeAtomicResponse(); return pioDelay; } Tick -Uart8250::write(Packet *pkt) +Uart8250::write(PacketPtr pkt) { - assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getSize() == 1); @@ -206,7 +202,7 @@ Uart8250::write(Packet *pkt) switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // write byte - cons->out(pkt->get()); + term->out(pkt->get()); platform->clearConsoleInt(); status &= ~TX_INT; if (UART_IER_THRI & IER) @@ -221,25 +217,33 @@ Uart8250::write(Packet *pkt) if (UART_IER_THRI & IER) { DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n"); - txIntrEvent.scheduleIntr(); + if (curTick - lastTxInt > 225 * SimClock::Int::ns) { + DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n", + curTick, lastTxInt); + txIntrEvent.process(); + } else { + DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n", + curTick, lastTxInt); + txIntrEvent.scheduleIntr(); + } } else { DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n"); if (txIntrEvent.scheduled()) - txIntrEvent.deschedule(); + deschedule(txIntrEvent); if (status & TX_INT) platform->clearConsoleInt(); status &= ~TX_INT; } - if ((UART_IER_RDI & IER) && cons->dataAvailable()) { + if ((UART_IER_RDI & IER) && term->dataAvailable()) { DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n"); rxIntrEvent.scheduleIntr(); } else { DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n"); if (rxIntrEvent.scheduled()) - rxIntrEvent.deschedule(); + deschedule(rxIntrEvent); if (status & RX_INT) platform->clearConsoleInt(); status &= ~RX_INT; @@ -264,7 +268,7 @@ Uart8250::write(Packet *pkt) panic("Tried to access a UART port that doesn't exist\n"); break; } - pkt->result = Packet::Success; + pkt->makeAtomicResponse(); return pioDelay; } @@ -325,42 +329,13 @@ Uart8250::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxintrwhen); UNSERIALIZE_SCALAR(txintrwhen); if (rxintrwhen != 0) - rxIntrEvent.schedule(rxintrwhen); + schedule(rxIntrEvent, rxintrwhen); if (txintrwhen != 0) - txIntrEvent.schedule(txintrwhen); + schedule(txIntrEvent, txintrwhen); } -BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart8250) - - Param pio_addr; - Param pio_latency; - SimObjectParam platform; - SimObjectParam sim_console; - SimObjectParam system; - -END_DECLARE_SIM_OBJECT_PARAMS(Uart8250) - -BEGIN_INIT_SIM_OBJECT_PARAMS(Uart8250) - - INIT_PARAM(pio_addr, "Device Address"), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000), - INIT_PARAM(platform, "platform"), - INIT_PARAM(sim_console, "The Simulator Console"), - INIT_PARAM(system, "system object") - -END_INIT_SIM_OBJECT_PARAMS(Uart8250) - -CREATE_SIM_OBJECT(Uart8250) +Uart8250 * +Uart8250Params::create() { - Uart8250::Params *p = new Uart8250::Params; - p->name = getInstanceName(); - p->pio_addr = pio_addr; - p->pio_delay = pio_latency; - p->platform = platform; - p->cons = sim_console; - p->system = system; - return new Uart8250(p); + return new Uart8250(this); } - -REGISTER_SIM_OBJECT("Uart8250", Uart8250) -