Пример #1
0
static void
i8250fifo(Uart* uart, int on)
{
	int i;
	Ctlr *ctlr;

	/*
	 * Toggle FIFOs:
	 * if none, do nothing;
	 * reset the Rx and Tx FIFOs;
	 * empty the Rx buffer and clear any interrupt conditions;
	 * if enabling, try to turn them on.
	 */
	ctlr = uart->regs;

	ilock(ctlr);
	if(!ctlr->fifo){
		csr8w(ctlr, Fcr, FIFOtclr|FIFOrclr);
		for(i = 0; i < 16; i++){
			csr8r(ctlr, Iir);
			csr8r(ctlr, Rbr);
		}
  
		ctlr->fena = 0;
		if(on){
			csr8w(ctlr, Fcr, FIFO4|FIFOena);
			if(!(csr8r(ctlr, Iir) & Ife))
				ctlr->fifo = 1;
			ctlr->fena = 1;
		}
	}
	iunlock(ctlr);
}
Пример #2
0
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);
		}
	}
}
Пример #3
0
static int
i8250getc(Uart* uart)
{
	Ctlr *ctlr;

	ctlr = uart->regs;
	while(!(csr8r(ctlr, Lsr) & Dr))
		delay(1);
	return csr8r(ctlr, Rbr);
}
Пример #4
0
void
putc(int c)
{
	int i;

	for(i = 0; !(csr8r(Lsr) & Thre) && i < 1000000; i++)
		;
	csr8o(Thr, (uchar)c);
	for(i = 0; !(csr8r(Lsr) & Thre) && i < 1000000; i++)
		;
}
Пример #5
0
static void
i8250putc(Uart *uart, int c)
{
	int i;
	Ctlr *ctlr;

	ctlr = uart->regs;
	for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
		delay(1);
	outb(ctlr->io+Thr, c);
	for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
		delay(1);
}
Пример #6
0
static void
i8250dumpregs(Ctlr* ctlr)
{
	int dlm, dll;
	int _uartprint(char*, ...);

	csr8w(ctlr, Lcr, Dlab);
	dlm = csr8r(ctlr, Dlm);
	dll = csr8r(ctlr, Dll);
	csr8w(ctlr, Lcr, 0);

	_uartprint("dlm %#ux dll %#ux\n", dlm, dll);
}
Пример #7
0
static void
ks8695_modemintr(Ureg*, void *arg)
{
	Ctlr *ctlr;
	Uart *uart;
	int old, r;

	uart = arg;
	ctlr = uart->regs;
	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;
	}
}
Пример #8
0
static int
ks8695_bits(Uart* uart, int bits)
{
	int lcr;
	Ctlr *ctlr;

	ctlr = uart->regs;
	lcr = csr8r(ctlr, Lcr) & ~WlsMASK;

	switch(bits){
	case 5:
		lcr |= Wls5;
		break;
	case 6:
		lcr |= Wls6;
		break;
	case 7:
		lcr |= Wls7;
		break;
	case 8:
		lcr |= Wls8;
		break;
	default:
		return -1;
	}
	csr8w(ctlr, Lcr, lcr);

	uart->bits = bits;

	return 0;
}
Пример #9
0
static int
i8250baud(Uart* uart, int baud)
{
#ifdef notdef				/* don't change the speed */
	ulong bgc;
	Ctlr *ctlr;
	extern int i8250freq;	/* In the config file */

	/*
	 * Set the Baud rate by calculating and setting the Baud rate
	 * Generator Constant. This will work with fairly non-standard
	 * Baud rates.
	 */
	if(i8250freq == 0 || baud <= 0)
		return -1;
	bgc = (i8250freq+8*baud-1)/(16*baud);

	ctlr = uart->regs;
	while(csr8r(ctlr, Usr) & Busy)
		delay(1);
	csr8w(ctlr, Lcr, Dlab);		/* begin kludge */
	csr8o(ctlr, Dlm, bgc>>8);
	csr8o(ctlr, Dll, bgc);
	csr8w(ctlr, Lcr, 0);
#endif
	uart->baud = baud;
	return 0;
}
Пример #10
0
static int
ks8695_parity(Uart* uart, int parity)
{
	int lcr;
	Ctlr *ctlr;

	ctlr = uart->regs;
	lcr = csr8r(ctlr, Lcr) & ~(Eps|Pen);

	switch(parity){
	case 'e':
		lcr |= Eps|Pen;
		break;
	case 'o':
		lcr |= Pen;
		break;
	case 'n':
	default:
		break;
	}
	csr8w(ctlr, Lcr, lcr);

	uart->parity = parity;

	return 0;
}
Пример #11
0
static Uart*
i8250pnp(void)
{
	int i;
	Ctlr *ctlr;
	Uart *head, *uart;

	head = i8250uart;
	for(i = 0; i < nelem(i8250uart); i++){
		/*
		 * Does it exist?
		 * Should be able to write/read the Scratch Pad
		 * and reserve the I/O space.
		 */
		uart = &i8250uart[i];
		ctlr = uart->regs;
		csr8o(ctlr, Scr, 0x55);
		if(csr8r(ctlr, Scr) == 0x55)
			continue;
		if(ioalloc(ctlr->io, 8, 0, uart->name) < 0)
			continue;
		if(uart == head)
			head = uart->next;
		else
			(uart-1)->next = uart->next;
	}

	return head;
}
Пример #12
0
static void
ks8695_putc(Uart *uart, int c)
{
	serialputc(c);
#ifdef ROT
	int i;
	Ctlr *ctlr;

	ctlr = uart->regs;
	for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 256; i++)
		delay(1);
	csr8w(ctlr, Thr, c);
	if(c == '\n')
		while((csr8r(ctlr, Lsr) & Temt) == 0){	/* let fifo drain */
			/* skip */
		}
#endif
}
Пример #13
0
static long
ks8695_status(Uart* uart, void* buf, long n, long offset)
{
	char *p;
	Ctlr *ctlr;
	uchar ier, lcr, mcr, msr;

	ctlr = uart->regs;
	p = malloc(READSTR);
	mcr = csr8r(ctlr, Mcr);
	msr = csr8r(ctlr, Msr);
	ier = INTRREG->en;
	lcr = csr8r(ctlr, Lcr);
	snprint(p, READSTR,
		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d ier=%ux\n"
		"dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",

		uart->baud,
		uart->hup_dcd, 
		(msr & Dsr) != 0,
		uart->hup_dsr,
		(lcr & WlsMASK) + 5,
		(ier & (1<<IRQums)) != 0, 
		(lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
		(mcr & Rts) != 0,
		(lcr & Stb) ? 2: 1,
		ctlr->fena,
		ier,

		uart->dev,
		uart->type,
		uart->ferr,
		uart->oerr, 
		(msr & Cts) ? " cts": "",
		(msr & Dsr) ? " dsr": "",
		(msr & Dcd) ? " dcd": "",
		(msr & Ri) ? " ring": ""
	);
	n = readstr(offset, buf, n, p);
	free(p);

	return n;
}
Пример #14
0
static void
i8250kick(Uart* uart)
{
	int i;
	Ctlr *ctlr;

	if(/* uart->cts == 0 || */ uart->blocked)
		return;

	if(!normalprint) {			/* early */
		if (uart->op < uart->oe)
			emptyoutstage(uart, uart->oe - uart->op);
		while ((i = uartstageoutput(uart)) > 0)
			emptyoutstage(uart, i);
		return;
	}

	/* nothing more to send? then disable xmit intr */
	ctlr = uart->regs;
	if (uart->op >= uart->oe && qlen(uart->oq) == 0 &&
	    csr8r(ctlr, Lsr) & Temt) {
		ctlr->sticky[Ier] &= ~Ethre;
		csr8w(ctlr, Ier, 0);
		return;
	}

	/*
	 *  128 here is an arbitrary limit to make sure
	 *  we don't stay in this loop too long.  If the
	 *  chip's output queue is longer than 128, too
	 *  bad -- presotto
	 */
	for(i = 0; i < 128; i++){
		if(!(csr8r(ctlr, Lsr) & Thre))
			break;
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
			break;
		csr8o(ctlr, Thr, *uart->op++);		/* start tx */
		ctlr->sticky[Ier] |= Ethre;
		csr8w(ctlr, Ier, 0);			/* intr when done */
	}
}
Пример #15
0
static int
rtl8139reset(Ctlr* ctlr)
{
	/*
	 * Soft reset the controller.
	 */
	csr8w(ctlr, Cr, Rst);
	while(csr8r(ctlr, Cr) & Rst)
		;

	return 0;
}
Пример #16
0
Uart*
i8250console(char* cfg)
{
	int i;
	Uart *uart;
	Ctlr *ctlr;
	char *cmd, *p;

	/*
	 * Before i8250pnp() is run can only set the console
	 * to 0 or 1 because those are the only uart structs which
	 * will be the same before and after that.
	 */
	if((p = getconf("console")) == nil && (p = cfg) == nil)
		return nil;
	i = strtoul(p, &cmd, 0);
	if(p == cmd)
		return nil;
	if((uart = uartconsole(i, cmd)) != nil){
		consuart = uart;
		return uart;
	}
	switch(i){
	default:
		return nil;
	case 0:
		uart = &i8250uart[0];
		break;
	case 1:
		uart = &i8250uart[1];
		break;	
	}

	/*
	 * Does it exist?
	 * Should be able to write/read
	 * the Scratch Pad.
	 */
	ctlr = uart->regs;
	csr8o(ctlr, Scr, 0x55);
	if(csr8r(ctlr, Scr) != 0x55)
		return nil;

	(*uart->phys->enable)(uart, 0);
	uartctl(uart, "b9600 l8 pn s1 i1");
	if(*cmd != '\0')
		uartctl(uart, cmd);

	consuart = uart;
	uart->console = 1;

	return uart;
}
Пример #17
0
static void
i8250putc(Uart* uart, int c)
{
	int i;
	Ctlr *ctlr;

	if (!normalprint) {		/* too early; use brute force */
		int s = splhi();

		while (!(((ulong *)PHYSCONS)[Lsr] & Thre))
			;
		((ulong *)PHYSCONS)[Thr] = c;
		coherence();
		splx(s);
		return;
	}

	ctlr = uart->regs;
	for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++)
		delay(1);
	csr8o(ctlr, Thr, (uchar)c);
	for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++)
		delay(1);
}
Пример #18
0
static void
vt6102promiscuous(void* arg, int on)
{
	int rcr;
	Ctlr *ctlr;
	Ether *edev;

	edev = arg;
	ctlr = edev->ctlr;
	rcr = csr8r(ctlr, Rcr);
	if(on)
		rcr |= Prom;
	else
		rcr &= ~Prom;
	csr8w(ctlr, Rcr, rcr);
}
Пример #19
0
static void
i8250fifo(Uart* uart, int level)
{
	Ctlr *ctlr;

	ctlr = uart->regs;
	if(ctlr->hasfifo == 0)
		return;

	/*
	 * Changing the FIFOena bit in Fcr flushes data
	 * from both receive and transmit FIFOs; there's
	 * no easy way to guarantee not losing data on
	 * the receive side, but it's possible to wait until
	 * the transmitter is really empty.
	 */
	ilock(ctlr);
	while(!(csr8r(ctlr, Lsr) & Temt))
		;

	/*
	 * Set the trigger level, default is the max.
	 * value.
	 * Some UARTs require FIFOena to be set before
	 * other bits can take effect, so set it twice.
	 */
	ctlr->fena = level;
	switch(level){
	case 0:
		break;
	case 1:
		level = FIFO1|FIFOena;
		break;
	case 4:
		level = FIFO4|FIFOena;
		break;
	case 8:
		level = FIFO8|FIFOena;
		break;
	default:
		level = FIFO14|FIFOena;
		break;
	}
	csr8w(ctlr, Fcr, level);
	csr8w(ctlr, Fcr, level);
	iunlock(ctlr);
}
Пример #20
0
static void
ks8695_dtr(Uart* uart, int on)
{
	Ctlr *ctlr;
	int r;

	/*
	 * Toggle DTR.
	 */
	ctlr = uart->regs;
	r = csr8r(ctlr, Mcr);
	if(on)
		r |= Dtr;
	else
		r &= ~Dtr;
	csr8w(ctlr, Mcr, r);
}
Пример #21
0
static void
ks8695_rts(Uart* uart, int on)
{
	Ctlr *ctlr;
	int r;

	/*
	 * Toggle RTS.
	 */
	ctlr = uart->regs;
	r = csr8r(ctlr, Mcr);
	if(on)
		r |= Rts;
	else
		r &= ~Rts;
	csr8w(ctlr, Mcr, r);
}
Пример #22
0
static int32_t
i8250status(Uart* uart, void* buf, int32_t n, int32_t offset)
{
	char *p;
	Ctlr *ctlr;
	uint8_t ier, lcr, mcr, msr;

	ctlr = uart->regs;
	p = malloc(READSTR);
	mcr = ctlr->sticky[Mcr];
	msr = csr8r(ctlr, Msr);
	ier = ctlr->sticky[Ier];
	lcr = ctlr->sticky[Lcr];
	snprint(p, READSTR,
		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
		"dev(%d) type(%d) framing(%d) overruns(%d) "
		"berr(%d) serr(%d)%s%s%s%s\n",

		uart->baud,
		uart->hup_dcd,
		(msr & Dsr) != 0,
		uart->hup_dsr,
		(lcr & WlsMASK) + 5,
		(ier & Ems) != 0,
		(lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
		(mcr & Rts) != 0,
		(lcr & Stb) ? 2: 1,
		ctlr->fena,

		uart->dev,
		uart->type,
		uart->ferr,
		uart->oerr,
		uart->berr,
		uart->serr,
		(msr & Cts) ? " cts": "",
		(msr & Dsr) ? " dsr": "",
		(msr & Dcd) ? " dcd": "",
		(msr & Ri) ? " ring": ""
	);
	n = readstr(offset, buf, n, p);
	free(p);

	return n;
}
Пример #23
0
static void
ks8695_break(Uart* uart, int ms)
{
	Ctlr *ctlr;
	int lcr;

	/*
	 * Send a break.
	 */
	if(ms == 0)
		ms = 200;

	ctlr = uart->regs;
	lcr = csr8r(ctlr, Lcr);
	csr8w(ctlr, Lcr, lcr|Brk);
	tsleep(&up->sleep, return0, 0, ms);
	csr8w(ctlr, Lcr, lcr);
}
Пример #24
0
static void
ks8695_kick(Uart* uart)
{
	int i;
	Ctlr *ctlr;

	if(uart->cts == 0 || uart->blocked)
		return;

	ctlr = uart->regs;
	for(i = 0; i < 16; i++){
		if(!(csr8r(ctlr, Lsr) & Thre))
			break;
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
			break;
		csr8w(ctlr, Thr, *uart->op++);
	}
}
Пример #25
0
static void
ks8695_fifo(Uart* uart, int level)
{
	Ctlr *ctlr;

	ctlr = uart->regs;

	/*
	 * Changing the FIFOena bit in Fcr flushes data
	 * from both receive and transmit FIFOs; there's
	 * no easy way to guarantee not losing data on
	 * the receive side, but it's possible to wait until
	 * the transmitter is really empty.
	 */
	ilock(ctlr);
	while(!(csr8r(ctlr, Lsr) & Temt))
		;

	/*
	 * Set the trigger level, default is the max.
	 * value.
	 */
	ctlr->fena = level;
	switch(level){
	case 0:
		break;
	case 1:
		level = FIFO1|FIFOena;
		break;
	case 4:
		level = FIFO4|FIFOena;
		break;
	case 8:
		level = FIFO8|FIFOena;
		break;
	default:
		level = FIFO14|FIFOena;
		break;
	}
	csr8w(ctlr, Fcr, level);
	iunlock(ctlr);
}
Пример #26
0
static void
ks8695_modemctl(Uart* uart, int on)
{
	Ctlr *ctlr;

	ctlr = uart->regs;
	ilock(&uart->tlock);
	if(on){
		INTRREG->en |= 1<<IRQums;	/* TO DO */
		uart->modem = 1;
		uart->cts = csr8r(ctlr, Msr) & Cts;
	}
	else{
		INTRREG->en &= ~(1<<IRQums);
		uart->modem = 0;
		uart->cts = 1;
	}
	iunlock(&uart->tlock);

	/* modem needs fifo */
	(*uart->phys->fifo)(uart, on);
}
Пример #27
0
static int
ks8695_stop(Uart* uart, int stop)
{
	int lcr;
	Ctlr *ctlr;

	ctlr = uart->regs;
	lcr = csr8r(ctlr, Lcr);
	switch(stop){
	case 1:
		lcr &= ~Stb;
		break;
	case 2:
		lcr |= Stb;
		break;
	default:
		return -1;
	}
	csr8w(ctlr, Lcr, lcr);
	uart->stop = stop;
	return 0;
}
Пример #28
0
static void
i8250modemctl(Uart* uart, int on)
{
	Ctlr *ctlr;

	ctlr = uart->regs;
	ilock(&uart->tlock);
	if(on){
		ctlr->sticky[Ier] |= Ems;
		csr8w(ctlr, Ier, 0);
		uart->modem = 1;
		uart->cts = csr8r(ctlr, Msr) & Cts;
	}
	else{
		ctlr->sticky[Ier] &= ~Ems;
		csr8w(ctlr, Ier, 0);
		uart->modem = 0;
		uart->cts = 1;
	}
	iunlock(&uart->tlock);

	/* modem needs fifo */
	(*uart->phys->fifo)(uart, on);
}
Пример #29
0
static void
i8250kick(Uart* uart)
{
	int i;
	Ctlr *ctlr;

	if(uart->cts == 0 || uart->blocked)
		return;

	/*
	 *  128 here is an arbitrary limit to make sure
	 *  we don't stay in this loop too long.  If the
	 *  chip's output queue is longer than 128, too
	 *  bad -- presotto
	 */
	ctlr = uart->regs;
	for(i = 0; i < 128; i++){
		if(!(csr8r(ctlr, Lsr) & Thre))
			break;
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
			break;
		outb(ctlr->io+Thr, *(uart->op++));
	}
}
Пример #30
0
static void
i8250enable(Uart* uart, int ie)
{
	int mode;
	Ctlr *ctlr;

	if (up == nil)
		return;				/* too soon */

	ctlr = uart->regs;

	/* omap only: set uart/irda/cir mode to uart */
	mode = csr8r(ctlr, Mdr);
	csr8o(ctlr, Mdr, (mode & ~Modemask) | Modeuart);

	ctlr->sticky[Lcr] = Wls8;		/* no parity */
	csr8w(ctlr, Lcr, 0);

	/*
	 * Check if there is a FIFO.
	 * Changing the FIFOena bit in Fcr flushes data
	 * from both receive and transmit FIFOs; there's
	 * no easy way to guarantee not losing data on
	 * the receive side, but it's possible to wait until
	 * the transmitter is really empty.
	 * Also, reading the Iir outwith i8250interrupt()
	 * can be dangerous, but this should only happen
	 * once, before interrupts are enabled.
	 */
	ilock(ctlr);
	if(!ctlr->checkfifo){
		/*
		 * Wait until the transmitter is really empty.
		 */
		while(!(csr8r(ctlr, Lsr) & Temt))
			;
		csr8w(ctlr, Fcr, FIFOena);
		if(csr8r(ctlr, Iir) & Ifena)
			ctlr->hasfifo = 1;
		csr8w(ctlr, Fcr, 0);
		ctlr->checkfifo = 1;
	}
	iunlock(ctlr);

	/*
	 * Enable interrupts and turn on DTR and RTS.
	 * Be careful if this is called to set up a polled serial line
	 * early on not to try to enable interrupts as interrupt-
	 * -enabling mechanisms might not be set up yet.
	 */
	if(ie){
		if(ctlr->iena == 0 && !ctlr->poll){
			irqenable(ctlr->irq, i8250interrupt, uart, uart->name);
			ctlr->iena = 1;
		}
		ctlr->sticky[Ier] = Erda;
//		ctlr->sticky[Mcr] |= Ie;		/* not on omap */
		ctlr->sticky[Mcr] = 0;
	}
	else{
		ctlr->sticky[Ier] = 0;
		ctlr->sticky[Mcr] = 0;
	}
	csr8w(ctlr, Ier, 0);
	csr8w(ctlr, Mcr, 0);

	(*uart->phys->dtr)(uart, 1);
	(*uart->phys->rts)(uart, 1);

	/*
	 * During startup, the i8259 interrupt controller is reset.
	 * This may result in a lost interrupt from the i8250 uart.
	 * The i8250 thinks the interrupt is still outstanding and does not
	 * generate any further interrupts. The workaround is to call the
	 * interrupt handler to clear any pending interrupt events.
	 * Note: this must be done after setting Ier.
	 */
	if(ie)
		i8250interrupt(nil, uart);
}