-
-}
-
-Fault
-Uart::read(MemReqPtr &req, uint8_t *data)
-{
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
- DPRINTF(Uart, " read register %#x\n", daddr);
-
-
-
-#ifdef ALPHA_TLASER
-
- switch (req->size) {
- case sizeof(uint64_t):
- *(uint64_t *)data = 0;
- break;
- case sizeof(uint32_t):
- *(uint32_t *)data = 0;
- break;
- case sizeof(uint16_t):
- *(uint16_t *)data = 0;
- break;
- case sizeof(uint8_t):
- *(uint8_t *)data = 0;
- break;
- }
-
- switch (daddr) {
- case 0x80: // Status Register
- if (readAddr == 3) {
- readAddr = 0;
- if (status & TX_INT)
- *data = (1 << 4);
- else if (status & RX_INT)
- *data = (1 << 5);
- else
- DPRINTF(Uart, "spurious read\n");
-
- } else {
- *data = (1 << 2);
- if (status & RX_INT)
- *data |= (1 << 0);
- }
- break;
-
- case 0xc0: // Data register (RX)
- if (!cons->dataAvailable())
- panic("No data to read");
-
- cons->in(*data);
-
- if (!cons->dataAvailable()) {
- platform->clearConsoleInt();
- status &= ~RX_INT;
- }
-
- DPRINTF(Uart, "read data register \'%c\' %2x\n",
- isprint(*data) ? *data : ' ', *data);
- break;
- }
-
-
-#else
-
-
- assert(req->size == 1);
-
- switch (daddr) {
- case 0x0:
- if (!(LCR & 0x80)) { // read byte
- if (cons->dataAvailable())
- cons->in(*data);
- else {
- *(uint8_t*)data = 0;
- // A limited amount of these are ok.
- DPRINTF(Uart, "empty read of RX register\n");
- }
- status &= ~RX_INT;
- platform->clearConsoleInt();
-
- if (cons->dataAvailable() && (IER & UART_IER_RDI))
- rxIntrEvent.scheduleIntr();
- } else { // dll divisor latch
- ;
- }
- break;
- case 0x1:
- if (!(LCR & 0x80)) { // Intr Enable Register(IER)
- *(uint8_t*)data = IER;
- } else { // DLM divisor latch MSB
- ;
- }
- break;
- case 0x2: // Intr Identification Register (IIR)
- DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
- if (status)
- *(uint8_t*)data = 0;
- else
- *(uint8_t*)data = 1;
- break;
- case 0x3: // Line Control Register (LCR)
- *(uint8_t*)data = LCR;
- break;
- case 0x4: // Modem Control Register (MCR)
- break;
- case 0x5: // Line Status Register (LSR)
- uint8_t lsr;
- lsr = 0;
- // check if there are any bytes to be read
- if (cons->dataAvailable())
- lsr = UART_LSR_DR;
- lsr |= UART_LSR_TEMT | UART_LSR_THRE;
- *(uint8_t*)data = lsr;
- break;
- case 0x6: // Modem Status Register (MSR)
- *(uint8_t*)data = 0;
- break;
- case 0x7: // Scratch Register (SCR)
- *(uint8_t*)data = 0; // doesn't exist with at 8250.
- break;
- default:
- panic("Tried to access a UART port that doesn't exist\n");
- break;
- }
-
-#endif
- return No_Fault;
-
-}
-
-Fault
-Uart::write(MemReqPtr &req, const uint8_t *data)
-{
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
-
- DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
-
-#ifdef ALPHA_TLASER
-
- switch (daddr) {
- case 0x80:
- readAddr = *data;
- switch (*data) {
- case 0x28: // Ack of TX
- if ((status & TX_INT) == 0)
- panic("Ack of transmit, though there was no interrupt");
-
- status &= ~TX_INT;
- platform->clearConsoleInt();
- break;
- case 0x00:
- case 0x01:
- case 0x03: // going to read RR3
- case 0x12:
- break;
- default:
- DPRINTF(Uart, "writing status register %#x \n",
- *(uint64_t *)data);
- break;
- }
- break;
-
- case 0xc0: // Data register (TX)
- cons->out(*(uint64_t *)data);
- platform->postConsoleInt();
- status |= TX_INT;
- break;
- }
-
-
-#else
- switch (daddr) {
- case 0x0:
- if (!(LCR & 0x80)) { // write byte
- cons->out(*(uint64_t *)data);
- platform->clearConsoleInt();
- status &= ~TX_INT;
- if (UART_IER_THRI & IER)
- txIntrEvent.scheduleIntr();
- } else { // dll divisor latch
- ;
- }
- break;
- case 0x1:
- if (!(LCR & 0x80)) { // Intr Enable Register(IER)
- IER = *(uint8_t*)data;
- if (UART_IER_THRI & IER)
- {
- DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
- txIntrEvent.scheduleIntr();
- }
- else
- {
- DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n");
- if (txIntrEvent.scheduled())
- txIntrEvent.deschedule();
- if (status & TX_INT)
- platform->clearConsoleInt();
- status &= ~TX_INT;
- }
-
- if ((UART_IER_RDI & IER) && cons->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();
- if (status & RX_INT)
- platform->clearConsoleInt();
- status &= ~RX_INT;
- }
- } else { // DLM divisor latch MSB
- ;
- }
- break;
- case 0x2: // FIFO Control Register (FCR)
- break;
- case 0x3: // Line Control Register (LCR)
- LCR = *(uint8_t*)data;
- break;
- case 0x4: // Modem Control Register (MCR)
- if (*(uint8_t*)data == (UART_MCR_LOOP | 0x0A))
- MCR = 0x9A;
- break;
- case 0x7: // Scratch Register (SCR)
- // We are emulating a 8250 so we don't have a scratch reg
- break;
- default:
- panic("Tried to access a UART port that doesn't exist\n");
- break;
- }
-#endif
-
- return No_Fault;
-}
-
-void
-Uart::dataAvailable()
-{
-#ifdef ALPHA_TLASER
- platform->postConsoleInt();
- status |= RX_INT;
-#else
-
- // if the kernel wants an interrupt when we have data
- if (IER & UART_IER_RDI)
- {
- platform->postConsoleInt();
- status |= RX_INT;
- }
-
-#endif