Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/bitsy/uartsa1110.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname bitsy/uartsa1110.c 2001/0529
## diff -e /dev/null /n/emeliedump/2001/0529/sys/src/9/bitsy/uartsa1110.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

#include	"../port/netif.h"

/* this isn't strictly a sa1110 driver.  The rts/cts stuff is h3650 specific */

enum
{
	/* ctl[0] bits */
	Parity=		1<<0,
	Even=		1<<1,
	Stop2=		1<<2,
	Bits8=		1<<3,
	SCE=		1<<4,	/* synchronous clock enable */
	RCE=		1<<5,	/* rx on falling edge of clock */
	TCE=		1<<6,	/* tx on falling edge of clock */

	/* ctl[3] bits */
	Rena=		1<<0,	/* receiver enable */
	Tena=		1<<1,	/* transmitter enable */
	Break=		1<<2,	/* force TXD3 low */
	Rintena=	1<<3,	/* enable receive interrupt */
	Tintena=	1<<4,	/* enable transmitter interrupt */
	Loopback=	1<<5,	/* loop back data */

	/* data bits */
	DEparity=	1<<8,	/* parity error */
	DEframe=	1<<9,	/* framing error */
	DEoverrun=	1<<10,	/* overrun error */

	/* status[0] bits */
	Tint=		1<<0,	/* transmit fifo half full interrupt */
	Rint0=		1<<1,	/* receiver fifo 1/3-2/3 full */
	Rint1=		1<<2,	/* receiver fifo not empty and receiver idle */
	Breakstart=	1<<3,
	Breakend=	1<<4,
	Fifoerror=	1<<5,	/* fifo error */

	/* status[1] bits */
	Tbusy=		1<<0,	/* transmitting */
	Rnotempty=	1<<1,	/* receive fifo not empty */
	Tnotfull=	1<<2,	/* transmit fifo not full */
	ParityError=	1<<3,
	FrameError=	1<<4,
	Overrun=	1<<5,
};

extern PhysUart sa1110physuart;

static Uart sa1110uart[2] = {
{	.regs	= UART3REGS,
	.name	= "serialport3",
	.freq	= ClockFreq,
	.bits	= 8,
	.stop	= 1,
	.parity	= 'n',
	.baud	= 115200,
	.phys	= &sa1110physuart,
	.special=0,
	.next	= &sa1110uart[1], },

{	.regs	= UART1REGS,
	.name	= "serialport1",
	.freq	= ClockFreq,
	.bits	= 8,
	.stop	= 1,
	.parity	= 'n',
	.baud	= 115200,
	.phys	= &sa1110physuart,
	.special=0,
	.next	= nil, },
};
static Uart* consuart;
static Uart* µcuart;

#define R(p) ((Uartregs*)(p->regs))

/*
 *  enable a port's interrupts.  set DTR and RTS
 */
static void
sa1110_uartenable(Uart *p, int intena)
{
	ulong s;

	s = R(p)->ctl[3] & ~(Rintena|Tintena|Rena|Tena);
	if(intena)
		R(p)->ctl[3] = s |Rintena|Tintena|Rena|Tena;
	else
		R(p)->ctl[3] = s | Rena|Tena;
}

/*
 *  disable interrupts. clear DTR, and RTS
 */
static void
sa1110_uartdisable(Uart *p)
{
	R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena);
}

static long
sa1110_uartstatus(Uart *p, void *buf, long n, long offset)
{
	char str[256];
	ulong ctl0;

	ctl0 = R(p)->ctl[0];
	snprint(str, sizeof(str),
		"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)%s%s%s%s\n",

		p->baud,
		p->hup_dcd, 
		0,
		p->hup_dsr,
		(ctl0 & Bits8) ? 8 : 7,
		0, 
		(ctl0 & Parity) ? ((ctl0 & Even) ? 'e' : 'o') : 'n',
		0,
		(ctl0 & Stop2) ? 2 : 1,
		1,

		p->dev,
		p->type,
		p->ferr,
		p->oerr, 
		"",
		"",
		"",
		"" );
	return readstr(offset, buf, n, str);
}

/*
 *  set the buad rate
 */
static int
sa1110_uartbaud(Uart *p, int rate)
{
	ulong brconst;
	ulong ctl3;

	if(rate <= 0)
		return -1;

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	brconst = p->freq/(16*rate) - 1;
	R(p)->ctl[1] = (brconst>>8) & 0xf;
	R(p)->ctl[2] = brconst & 0xff;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	p->baud = rate;
	return 0;
}

/*
 *  send a break
 */
static void
sa1110_uartbreak(Uart *p, int ms)
{
	if(ms == 0)
		ms = 200;

	R(p)->ctl[3] |= Break;
	tsleep(&up->sleep, return0, 0, ms);
	R(p)->ctl[3] &= ~Break;
}

/*
 *  set bits/char
 */
static int
sa1110_uartbits(Uart *p, int n)
{
	ulong ctl0, ctl3;

	ctl0 = R(p)->ctl[0];
	switch(n){
	case 7:
		ctl0 &= ~Bits8;
		break;
	case 8:
		ctl0 |= Bits8;
		break;
	default:
		return -1;
	}

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	R(p)->ctl[0] = ctl0;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	p->bits = n;
	return 0;
}

/*
 *  set stop bits
 */
static int
sa1110_uartstop(Uart *p, int n)
{
	ulong ctl0, ctl3;

	ctl0 = R(p)->ctl[0];
	switch(n){
	case 1:
		ctl0 &= ~Stop2;
		break;
	case 2:
		ctl0 |= Stop2;
		break;
	default:
		return -1;
	}

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	R(p)->ctl[0] = ctl0;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	p->stop = n;
	return 0;
}

/*
 *  turn on/off rts
 */
static void
sa1110_uartrts(Uart*, int)
{
}

/*
 *  turn on/off dtr
 */
static void
sa1110_uartdtr(Uart*, int)
{
}

/*
 *  turn on/off modem flow control on/off (rts/cts)
 */
static void
sa1110_uartmodemctl(Uart *p, int on)
{
	if(on) {
	} else {
		p->cts = 1;
	}
}

/*
 *  set parity
 */
static int
sa1110_uartparity(Uart *p, int type)
{
	ulong ctl0, ctl3;

	ctl0 = R(p)->ctl[0];
	switch(type){
	case 'e':
		ctl0 |= Parity|Even;
		break;
	case 'o':
		ctl0 |= Parity;
		break;
	default:
		ctl0 &= ~(Parity|Even);
		break;
	}

	/* disable */
	ctl3 = R(p)->ctl[3];
	R(p)->ctl[3] = 0;

	R(p)->ctl[0] = ctl0;

	/* reenable */
	R(p)->ctl[3] = ctl3;

	return 0;
}

/*
 *  restart output if not blocked and OK to send
 */
static void
sa1110_uartkick(Uart *p)
{
	int i;

	R(p)->ctl[3] &= ~Tintena;

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

	for(i = 0; i < 1024; i++){
		if(!(R(p)->status[1] & Tnotfull)){
			R(p)->ctl[3] |= Tintena;
			break;
		}
		if(p->op >= p->oe && uartstageoutput(p) == 0)
			break;
		R(p)->data = *p->op++;
	}
}

/*
 *  take an interrupt
 */
static void
sa1110_uartintr(Ureg*, void *x)
{
	Uart *p;
	ulong s;
	Uartregs *regs;

	p = x;
	regs = p->regs;

	/* receiver interrupt, snarf bytes */
	while(regs->status[1] & Rnotempty)
		uartrecv(p, regs->data);

	/* remember and reset interrupt causes */
	s = regs->status[0];
	regs->status[0] |= s;

	if(s & Tint){
		/* transmitter interrupt, restart */
		uartkick(p);
	}

	if(s & (ParityError|FrameError|Overrun)){
		if(s & ParityError)
			p->parity++;
		if(s & FrameError)
			p->ferr++;
		if(s & Overrun)
			p->oerr++;
	}

	/* receiver interrupt, snarf bytes */
	while(regs->status[1] & Rnotempty)
		uartrecv(p, regs->data);
}

static Uart*
sa1110_pnp(void)
{
	return sa1110uart;
}

PhysUart sa1110physuart = {
	.name=		"sa1110",
	.pnp= 		sa1110_pnp,
	.enable=	sa1110_uartenable,
	.disable=	sa1110_uartdisable,
	.bits=		sa1110_uartbits,
	.kick=		sa1110_uartkick,
	.modemctl=	sa1110_uartmodemctl,
	.baud=		sa1110_uartbaud,
	.stop=		sa1110_uartstop,
	.parity=	sa1110_uartparity,
	.dobreak=	sa1110_uartbreak,
	.rts=		sa1110_uartrts,
	.dtr=		sa1110_uartdtr,
	.status=	sa1110_uartstatus,
};

/*
 *  for iprint, just write it
 */
static void
sa1110puts(char *str, int n)
{
	Uartregs *ur;

	if(consuart == nil)
		return;
	ur = consuart->regs;
	while(n-- > 0){
		/* wait for output ready */
		while((ur->status[1] & Tnotfull) == 0)
			;
		ur->data = *str++;
	}
	while((ur->status[1] & Tbusy))
		;
}

/*
 *  for iprint, just write it
 */
void
serialµcputs(uchar *str, int n)
{
	Uartregs *ur;

	if(µcuart == nil)
		return;
	ur = µcuart->regs;
	while(n-- > 0){
		/* wait for output ready */
		while((ur->status[1] & Tnotfull) == 0)
			;
		ur->data = *str++;
	}
	while((ur->status[1] & Tbusy))
		;
}

typedef struct Gpclkregs Gpclkregs;
struct Gpclkregs
{
	ulong	r0;
	ulong	r1;
	ulong	dummya;
	ulong	r2;
	ulong	r3;
};

enum
{
	/* gpclk register 0 */
	Gpclk_sus=	1<<0,	/* set uart mode */
};

Gpclkregs *gpclkregs;

/*
 *  setup all uarts (called early by main() to allow debugging output to
 *  a serial port)
 */
void
sa1110_uartsetup(int console)
{
	Uart *p;

	/* external serial port (eia0) */
	p = &sa1110uart[0];
	p->regs = mapspecial(UART3REGS, 64);

	/* set eia0 up as a console */
	if(console){
		uartctl(p, "b115200 l8 pn s1");
		consuart = p;
		(*p->phys->enable)(p, 0);
		serialputs = sa1110puts;
		p->console = 1;
	}
	intrenable(IRQ, IRQuart3, sa1110_uartintr, p, p->name);

	/* port for talking to microcontroller (eia1) */
	gpclkregs = mapspecial(GPCLKREGS, 64);
	gpclkregs->r0 = Gpclk_sus;	/* set uart mode */

	p = &sa1110uart[1];
	p->regs = mapspecial(UART1REGS, 64);
	uartctl(p, "b115200 l8 pn s1");
	µcuart = p;
	(*p->phys->enable)(p, 0);
	intrenable(IRQ, IRQuart1b, sa1110_uartintr, p, p->name);
}
.
## diffname bitsy/uartsa1110.c 2001/0605
## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/uartsa1110.c /n/emeliedump/2001/0605/sys/src/9/bitsy/uartsa1110.c
389,393c
	.parity=		sa1110_uartparity,
	.dobreak=		sa1110_uartbreak,
	.rts=			sa1110_uartrts,
	.dtr=			sa1110_uartdtr,
	.status=		sa1110_uartstatus,
.
382,383c
	.enable=		sa1110_uartenable,
	.disable=		sa1110_uartdisable,
.
76,77c
	.special	= 0,
	.next		= nil, },
.
70,72c
	.freq		= ClockFreq,
	.bits		= 8,
	.stop		= 1,
.
68c
{	.regs		= UART1REGS,
.
65,66c
	.special	= 0,
	.next		= &sa1110uart[1], },
.
59,61c
	.freq		= ClockFreq,
	.bits		= 8,
	.stop		= 1,
.
57c
{	.regs		= UART3REGS,
.
51c
	Overrun=		1<<5,
.
48c
	Tnotfull=		1<<2,	/* transmit fifo not full */
.
43c
	Fifoerror=		1<<5,	/* fifo error */
.
33,34c
	DEparity=		1<<8,	/* parity error */
	DEframe=		1<<9,	/* framing error */
.
28,29c
	Rintena=		1<<3,	/* enable receive interrupt */
	Tintena=		1<<4,	/* enable transmitter interrupt */
.
20c
	SCE=			1<<4,	/* synchronous clock enable */
.
11c
/* this isn't strictly an sa1110 driver.  The rts/cts stuff is h3650 specific */
.
## diffname bitsy/uartsa1110.c 2001/0606
## diff -e /n/emeliedump/2001/0605/sys/src/9/bitsy/uartsa1110.c /n/emeliedump/2001/0606/sys/src/9/bitsy/uartsa1110.c
486a
	p->special = 1;
.
75a
	.putc		= µcputc,
.
## diffname bitsy/uartsa1110.c 2001/0618
## diff -e /n/emeliedump/2001/0606/sys/src/9/bitsy/uartsa1110.c /n/emeliedump/2001/0618/sys/src/9/bitsy/uartsa1110.c
439,448d
## diffname bitsy/uartsa1110.c 2001/0619
## diff -e /n/emeliedump/2001/0618/sys/src/9/bitsy/uartsa1110.c /n/emeliedump/2001/0619/sys/src/9/bitsy/uartsa1110.c
480a
}

static  void
uartcpy(Uartregs *to, Uartregs *from)
{
	to->ctl[0] = from->ctl[0];
//	to->ctl[1] = from->ctl[1];
//	to->ctl[2] = from->ctl[2];
	to->ctl[3] = from->ctl[3];

}

static void
sa1110_uartpower(Uart *p, int powerup)
{
	if (powerup) {
		/* power up, restore the registers */
		uartcpy(R(p), SR(p));
		R(p)->status[0] = R(p)->status[0];
	} else {
		/* power down, save the registers */
		uartcpy(SR(p), R(p));
	}
.
475a
	p->saveregs = xalloc(sizeof(Uartregs));
.
459c
	p->saveregs = xalloc(sizeof(Uartregs));
.
394a
	.power=		sa1110_uartpower,
.
83c
#define R(p) ((Uartregs*)((p)->regs))
#define SR(p) ((Uartregs*)((p)->saveregs))
.
56c
//static
Uart sa1110uart[2] = {
.
12a
static void sa1110_uartpower(Uart *, int);

.
## diffname bitsy/uartsa1110.c 2002/0412
## diff -e /n/emeliedump/2001/0619/sys/src/9/bitsy/uartsa1110.c /n/emeliedump/2002/0412/sys/src/9/bitsy/uartsa1110.c
471a
		consuart = p;
.
470d
468d
405,425d
399a
	.getc=		sa1110_getc,
	.putc=		sa1110_putc,
.
383a
static int
sa1110_getc(Uart *uart)
{
	Uartregs *ur;

	ur = uart->regs;
	while((ur->status[1] & Rnotempty) == 0)
		;
	return ur->data;
}

static void
sa1110_putc(Uart *uart, int c)
{
	Uartregs *ur;

	ur = uart->regs;
	/* wait for output ready */
	while((ur->status[1] & Tnotfull) == 0)
		;
	ur->data = c;
	while((ur->status[1] & Tbusy))
		;
}

.
83d
## diffname bitsy/uartsa1110.c 2002/1112
## diff -e /n/emeliedump/2002/0412/sys/src/9/bitsy/uartsa1110.c /n/emeliedump/2002/1112/sys/src/9/bitsy/uartsa1110.c
484c
	p->regs = mapspecial(UART1REGS, sizeof(Uartregs));
.
480c
	gpclkregs = mapspecial(GPCLKREGS, sizeof(Gpclkregs));
.
468c
	p->regs = mapspecial(UART3REGS, sizeof(Uartregs));
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.