Beispiel #1
0
/*
 *  we save up input characters till clock time to reduce
 *  per character interrupt overhead.
 */
static void
uartclock(void)
{
	Uart *p;

	ilock(&uartalloc);
	for(p = uartalloc.elist; p; p = p->elist){

		/* this hopefully amortizes cost of qproduce to many chars */
		if(p->iw != p->ir){
			ilock(&p->rlock);
			uartstageinput(p);
			iunlock(&p->rlock);
		}

		/* hang up if requested */
		if(p->dohup){
			qhangup(p->iq, 0);
			qhangup(p->oq, 0);
			p->dohup = 0;
		}

		/* this adds hysteresis to hardware/software flow control */
		if(p->ctsbackoff){
			ilock(&p->tlock);
			if(p->ctsbackoff){
				if(--(p->ctsbackoff) == 0)
					(*p->phys->kick)(p);
			}
			iunlock(&p->tlock);
		}
		uartkick(p);		/* keep it moving */
	}
	iunlock(&uartalloc);
}
Beispiel #2
0
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();
}
Beispiel #3
0
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);
}
Beispiel #4
0
static void
axpinterrupt(Ureg*, void* arg)
{
	int work;
	Cc *cc;
	Ctlr *ctlr;
	u32int ics;
	u16int r, sr;

	work = 0;
	ctlr = arg;
	ics = csr32r(ctlr, Ics);
	if(ics & 0x0810C000)
		print("%s: unexpected interrupt %#ux\n", ctlr->name, ics);
	if(!(ics & 0x00002000)) {
		/* we get a steady stream of these on consoles */
		// print("%s: non-doorbell interrupt\n", ctlr->name);
		ctlr->gcb->gcw2 = 0x0001;	/* set Gintack */
		return;
	}

//	while(work to do){
		cc = ctlr->cc;
		for(sr = xchgw(&ctlr->gcb->isr, 0); sr != 0; sr >>= 1){
			if(sr & 0x0001)
				work++, axprecv(cc);
			cc++;
		}
		cc = ctlr->cc;
		for(sr = xchgw(&ctlr->gcb->osr, 0); sr != 0; sr >>= 1){
			if(sr & 0x0001)
				work++, uartkick(&cc->Uart);
			cc++;
		}
		cc = ctlr->cc;
		for(sr = xchgw(&ctlr->gcb->csr, 0); sr != 0; sr >>= 1){
			if(sr & 0x0001)
				work++, wakeup(cc);
			cc++;
		}
		cc = ctlr->cc;
		for(sr = xchgw(&ctlr->gcb->msr, 0); sr != 0; sr >>= 1){
			if(sr & 0x0001)
				work++, axpmc(cc);
			cc++;
		}
		cc = ctlr->cc;
		for(sr = xchgw(&ctlr->gcb->esr, 0); sr != 0; sr >>= 1){
			if(sr & 0x0001){
				r = cc->ccb->ms;
				if(r & Oe)
					cc->oerr++;
				if(r & Pe)
					cc->perr++;
				if(r & Fe)
					cc->ferr++;
				if (r & (Oe|Pe|Fe))
					work++;
			}
			cc++;
		}
//	}
	/* only meaningful if we don't share the irq */
	if (0 && !work)
		print("%s: interrupt with no work\n", ctlr->name);
	csr32w(ctlr, Pdb, 1);		/* clear doorbell interrupt */
	ctlr->gcb->gcw2 = 0x0001;	/* set Gintack */
}
Beispiel #5
0
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;
		}
	}
}
Beispiel #6
0
void
serialkick(void)
{
	uartkick(&i8250uart[CONSOLE]);
}
Beispiel #7
0
static void
ks8695_txintr(Ureg*, void* arg)
{
	uartkick(arg);
}