## 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