## diffname bitsy/sa1110uart.c 2000/1018
## diff -e /dev/null /n/emeliedump/2000/1018/sys/src/9/bitsy/sa1110uart.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 sa1100 driver. The rts/cts stuff is h3650 specific */
/* hardware registers */
typedef struct Uartregs Uartregs;
struct Uartregs
{
ulong ctl[4];
ulong dummya;
ulong data;
ulong dummyb;
ulong status[2];
};
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,
};
Uartregs *uart3regs = UART3REGS;
static void sa1100_uartbaud(Uart *p, int rate);
static void sa1100_uartkick(Uart *p);
static void sa1100_uartrts(Uart *p, int on);
static void sa1100_uartintr(Ureg*, void*);
static void sa1100_uartbreak(Uart*, int);
static void sa1100_uartbits(Uart*, int);
static void sa1100_uartparity(Uart*, int);
static void sa1100_uartmodemctl(Uart*, int);
static void sa1100_uartstop(Uart*, int);
static void sa1100_uartdtr(Uart*, int);
static long sa1100_uartstatus(Uart*, void*, long, long);
static void sa1100_uartenable(Uart*, int);
static void sa1100_uartdisable(Uart*);
PhysUart sa1100_uart = {
.enable= sa1100_uartenable,
.disable= sa1100_uartdisable,
.bits= sa1100_uartbits,
.kick= sa1100_uartkick,
.intr= sa1100_uartintr,
.modemctl= sa1100_uartmodemctl,
.baud= sa1100_uartbaud,
.stop= sa1100_uartstop,
.parity= sa1100_uartparity,
.dobreak= sa1100_uartbreak,
.rts= sa1100_uartrts,
.dtr= sa1100_uartdtr,
.status= sa1100_uartstatus,
};
#define R(p) ((Uartregs*)(p->regs))
/*
* enable a port's interrupts. set DTR and RTS
*/
static void
sa1100_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
sa1100_uartdisable(Uart *p)
{
R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena);
}
static long
sa1100_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->frame,
p->overrun,
"",
"",
"",
"" );
return readstr(offset, buf, n, str);
}
/*
* set the buad rate
*/
static void
sa1100_uartbaud(Uart *p, int rate)
{
ulong brconst;
if(rate <= 0)
return;
brconst = p->freq/(16*rate) - 1;
R(p)->ctl[1] = (brconst>>8) & 0xf;
R(p)->ctl[2] = brconst;
p->baud = rate;
}
/*
* send a break
*/
static void
sa1100_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 void
sa1100_uartbits(Uart *p, int n)
{
switch(n){
case 7:
R(p)->ctl[0] &= ~Bits8;
break;
case 8:
R(p)->ctl[0] |= Bits8;
break;
default:
error(Ebadarg);
}
}
/*
* set stop bits
*/
static void
sa1100_uartstop(Uart *p, int n)
{
switch(n){
case 1:
R(p)->ctl[0] &= ~Stop2;
break;
case 2:
R(p)->ctl[0] |= Stop2;
break;
default:
error(Ebadarg);
}
}
/*
* turn on/off rts
*/
static void
sa1100_uartrts(Uart*, int)
{
}
/*
* turn on/off dtr
*/
static void
sa1100_uartdtr(Uart*, int)
{
}
/*
* turn on/off modem flow control on/off (rts/cts)
*/
static void
sa1100_uartmodemctl(Uart *p, int on)
{
if(on) {
} else {
p->cts = 1;
}
}
/*
* set parity
*/
static void
sa1100_uartparity(Uart *p, int type)
{
switch(type){
case 'e':
R(p)->ctl[0] |= Parity|Even;
break;
case 'o':
R(p)->ctl[0] |= Parity;
break;
default:
R(p)->ctl[0] &= ~(Parity|Even);
break;
}
}
/*
* restart output if not blocked and OK to send
*/
static void
sa1100_uartkick(Uart *p)
{
int i;
R(p)->ctl[3] &= ~Tintena;
if(p->cts == 0 || p->blocked)
return;
/*
* 128 here is an arbitrary limit to make sure
* we don't stay in this loop too long. If the
* chips output queue is longer than 128, too
* bad -- presotto
*/
for(i = 0; i < 128; 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++;
}
}
/*
* for iprint, just write it
*/
void
serialputs(char *str, int n)
{
Uartregs *ur;
ur = uart3regs;
while(n-- > 0){
/* wait for output ready */
while((ur->status[1] & Tnotfull) == 0)
;
ur->data = *str++;
}
while((ur->status[1] & Tbusy))
;
}
/*
* take an interrupt
*/
static void
sa1100_uartintr(Ureg*, void *x)
{
Uart *p;
ulong s;
Uartregs *regs;
p = x;
regs = p->regs;
/* remember and reset interrupt causes */
s = regs->status[0];
regs->status[0] |= s;
if(s & Tint){
/* transmitter interrupt, restart */
uartkick(p);
}
/* receiver interrupt, snarf bytes */
while(regs->status[1] & Rnotempty)
uartrecv(p, regs->data);
if(s & (ParityError|FrameError|Overrun)){
if(s & ParityError)
p->parity++;
if(s & FrameError)
p->frame++;
if(s & Overrun)
p->overrun++;
}
}
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
sa1100_uartsetup(int console)
{
Uart *p;
Uartregs *uartregs;
/* external serial port (eia0) */
uart3regs = mapspecial(UART3REGS, 64);
p = uartsetup(&sa1100_uart, uart3regs, ClockFreq, "serialport3");
intrenable(IRQuart3, sa1100_uartintr, p, p->name);
/* set eia0 up as a console */
if(console)
uartspecial(p, 115200, &kbdq, &printq, kbdcr2nl);
/* port for talking to microcontroller (eia1) */
gpclkregs = mapspecial(GPCLKREGS, 64);
gpclkregs->r0 = Gpclk_sus; /* set uart mode */
uartregs = mapspecial(UART1REGS, 64);
p = uartsetup(&sa1100_uart, uartregs, ClockFreq, "serialport1");
sa1100_uartbaud(p, 115200);
intrenable(IRQuart1b, sa1100_uartintr, p, p->name);
}
.
## diffname bitsy/sa1110uart.c 2000/1019
## diff -e /n/emeliedump/2000/1018/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2000/1019/sys/src/9/bitsy/sa1110uart.c
396,397c
uart1regs = mapspecial(UART1REGS, 64);
p = uartsetup(&sa1100_uart, uart1regs, ClockFreq, "serialport1");
.
382d
353a
/* receiver interrupt, snarf bytes */
while(regs->status[1] & Rnotempty)
uartrecv(p, regs->data);
.
342,345d
332a
/* receiver interrupt, snarf bytes */
while(regs->status[1] & Rnotempty)
uartrecv(p, regs->data);
.
268a
/* reenable */
R(p)->ctl[3] = ctl3;
.
257a
ulong ctl3;
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
.
221a
/* reenable */
R(p)->ctl[3] = ctl3;
.
211a
ulong ctl3;
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
.
203a
/* reenable */
R(p)->ctl[3] = ctl3;
.
193a
ulong ctl3;
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
.
170a
/* reenable */
R(p)->ctl[3] = ctl3;
.
169c
R(p)->ctl[2] = brconst & 0xff;
.
166a
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
.
162a
ulong ctl3;
.
65a
Uartregs *uart1regs = UART1REGS ;
.
## diffname bitsy/sa1110uart.c 2000/1021
## diff -e /n/emeliedump/2000/1019/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2000/1021/sys/src/9/bitsy/sa1110uart.c
436c
uartspecial(p, 115200, 0, 0, µcputc);
.
355a
* for iprint, just write it
*/
void
serialµcputs(uchar *str, int n)
{
Uartregs *ur;
ur = uart1regs;
while(n-- > 0){
/* wait for output ready */
while((ur->status[1] & Tnotfull) == 0)
;
ur->data = *str++;
}
while((ur->status[1] & Tbusy))
;
}
/*
.
## diffname bitsy/sa1110uart.c 2000/1106
## diff -e /n/emeliedump/2000/1021/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2000/1106/sys/src/9/bitsy/sa1110uart.c
319,325c
for(i = 0; i < 1024; i++){
.
## diffname bitsy/sa1110uart.c 2000/1121
## diff -e /n/emeliedump/2000/1106/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2000/1121/sys/src/9/bitsy/sa1110uart.c
13,23d
## diffname bitsy/sa1110uart.c 2000/1205
## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2000/1205/sys/src/9/bitsy/sa1110uart.c
439c
intrenable(IRQ, IRQuart1b, sa1100_uartintr, p, p->name);
.
427c
intrenable(IRQ, IRQuart3, sa1100_uartintr, p, p->name);
.
## diffname bitsy/sa1110uart.c 2001/0117
## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2001/0117/sys/src/9/bitsy/sa1110uart.c
436a
.
## diffname bitsy/sa1110uart.c 2001/0529 # deleted
## diff -e /n/emeliedump/2001/0117/sys/src/9/bitsy/sa1110uart.c /n/emeliedump/2001/0529/sys/src/9/bitsy/sa1110uart.c
1,441d
|