static void interrupt(Ureg*, void *arg) { Uart *uart; u32int *ap; uart = arg; ap = (u32int*)uart->regs; coherence(); if(0 && (ap[Irq] & UartIrq) == 0) return; if(ap[MuLsr] & TxRdy) uartkick(uart); if(ap[MuLsr] & RxRdy){ //if(uart->console){ // if(uart->opens == 1) // uart->putc = kbdcr2nl; // else // uart->putc = nil; //} do{ uartrecv(uart, ap[MuIo] & 0xFF); }while(ap[MuLsr] & RxRdy); } coherence(); }
static void ks8695_rxintr(Ureg*, void* arg) { Ctlr *ctlr; Uart *uart; int lsr, r; /* handle line error status here as well */ uart = arg; ctlr = uart->regs; while((lsr = csr8r(ctlr, Lsr) & LsrInput) != 0){ /* * Consume any received data. * If the received byte came in with a break, * parity or framing error, throw it away; * overrun is an indication that something has * already been tossed. */ if(lsr & (FIFOerr|Oe)) uart->oerr++; if(lsr & Pe) uart->perr++; if(lsr & Fe) uart->ferr++; if(lsr & Dr){ r = csr8r(ctlr, Rbr); if(!(lsr & (Bi|Fe|Pe))) uartrecv(uart, r); } } }
static void uartrxintr(Ureg*, void* arg) { Uart *p = arg; intrclear(UARTRXbit(p->port), 0); p->inters++; p->rinters++; uartrecv(p); }
/* only called from interrupt service */ static void axprecv(Cc* cc) { Ccb *ccb; uchar *ep, *mem, *rp, *wp; ccb = cc->ccb; mem = (uchar*)cc->ctlr->gcb; rp = mem + ccb->ibrp; wp = mem + ccb->ibwp; ep = mem + ccb->ibea; while(rp != wp){ uartrecv(cc, *rp++); /* ilocks cc->tlock */ if(rp > ep) rp = mem + ccb->ibsa; ccb->ibrp = rp - mem; } }
static void oxinterrupt(Ureg *, void *arg) { Ctlr *ctlr; Port *port; Uart *uart; int i, old; u8int val; char ch; ctlr = arg; ilock(ctlr); if(!(ctlr->im & ctlr->mem[Gis])){ iunlock(ctlr); return; } for(i = 0; i < ctlr->nport; ++i){ if(!(ctlr->im & 1<<i)) continue; port = &ctlr->port[i]; uart = port; /* "Come Clarity" */ switch(port->mem[Isr] & 0x3f){ case 0x06: /* Receiver status error */ case 0x04: /* Receiver data available */ case 0x0c: /* Receiver time-out */ for(;;){ val = port->mem[Lsr]; if(!(val & 1<<0)) /* RxRDY */ break; if(val & 1<<1) /* Overrun Error */ uart->oerr++; if(val & 1<<2) /* Parity Error */ uart->perr++; if(val & 1<<3) /* Framing Error */ uart->ferr++; ch = port->mem[Rhr]; if(!(val & 1<<7)) /* Data Error */ uartrecv(uart, ch); } break; case 0x02: /* Transmitter THR empty */ uartkick(uart); break; case 0x00: /* Modem status change */ val = port->mem[Msr]; if(val & 1<<0){ /* Delta nCTS */ ilock(&uart->tlock); old = uart->cts; uart->cts = val & 1<<4; /* CTS */ if(!old && uart->cts) uart->ctsbackoff = 2; iunlock(&uart->tlock); } if(val & 1<<1){ /* Delta nDSR */ old = val & 1<<5; /* DSR */ if(!old && uart->dsr && uart->hup_dsr) uart->dohup = 1; uart->dsr = old; } port->ri = val & 1<<6; /* RI */ if(val & 1<<3){ /* Delta nDCD */ old = val & 1<<7; /* DCD */ if(!old && uart->dcd && uart->hup_dcd) uart->dohup = 1; uart->dcd = old; } break; } } iunlock(ctlr); }
static void i8250interrupt(Ureg*, void* arg) { Ctlr *ctlr; Uart *uart; int iir, lsr, old, r; uart = arg; ctlr = uart->regs; for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){ switch(iir & IirMASK){ case Ims: /* Ms interrupt */ r = csr8r(ctlr, Msr); if(r & Dcts){ ilock(&uart->tlock); old = uart->cts; uart->cts = r & Cts; if(old == 0 && uart->cts) uart->ctsbackoff = 2; iunlock(&uart->tlock); } if(r & Ddsr){ old = r & Dsr; if(uart->hup_dsr && uart->dsr && !old) uart->dohup = 1; uart->dsr = old; } if(r & Ddcd){ old = r & Dcd; if(uart->hup_dcd && uart->dcd && !old) uart->dohup = 1; uart->dcd = old; } break; case Ithre: /* Thr Empty */ uartkick(uart); break; case Irda: /* Received Data Available */ case Irls: /* Receiver Line Status */ case Ictoi: /* Character Time-out Indication */ /* * Consume any received data. * If the received byte came in with a break, * parity or framing error, throw it away; * overrun is an indication that something has * already been tossed. */ while((lsr = csr8r(ctlr, Lsr)) & Dr){ if(lsr & (FIFOerr|Oe)) uart->oerr++; if(lsr & Pe) uart->perr++; if(lsr & Fe) uart->ferr++; r = csr8r(ctlr, Rbr); if(!(lsr & (Bi|Fe|Pe))) uartrecv(uart, r); } break; default: iprint("weird uart interrupt type %#2.2uX\n", iir); break; } } }