📄 uartsaturn.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "msaturn.h"enum{ UartAoffs = Saturn + 0x0a00, UartBoffs = Saturn + 0x0b00, Nuart = 2, Baudfreq = 14745600 / 16, Lcr_div = RBIT(1, uchar), Lcr_peven = RBIT(3, uchar), Lcr_pen = RBIT(4, uchar), Lcr_stop = RBIT(5, uchar), Lcr_wrdlenmask = RBIT(6, uchar) | RBIT(7, uchar), Lcr_wrdlenshift = 0, Lsr_tbre = RBIT(2, uchar), Fcr_txreset = RBIT(5, uchar), Fcr_rxreset = RBIT(6, uchar), Iir_txempty = RBIT(5, uchar), Iir_rxfull = RBIT(6, uchar), Iir_rxerr = RBIT(7, uchar), Ier_rxerr = RBIT(5, uchar), Ier_txempty = RBIT(6, uchar), Ier_rxfull = RBIT(7, uchar), Lsr_rxavail = RBIT(7, uchar), Txsize = 16, Rxsize = 16,};typedef struct Saturnuart Saturnuart;struct Saturnuart { uchar rxb;#define txb rxb#define dll rxb uchar ier; // Interrupt enable, divisor latch#define dlm ier uchar iir; // Interrupt identification, fifo control#define fcr iir uchar lcr; // Line control register uchar f1; uchar lsr; // Line status register ushort f2;};typedef struct UartData UartData;struct UartData { int suno; /* saturn uart number: 0 or 1 */ Saturnuart *su; char *rxbuf; char *txbuf; int initialized; int enabled;} uartdata[Nuart];extern PhysUart saturnphysuart;Uart suart[Nuart] = { { .name = "SaturnUart1", .baud = 19200, .bits = 8, .stop = 1, .parity = 'n', .phys = &saturnphysuart, .special = 0, }, { .name = "SaturnUart2", .baud = 115200, .bits = 8, .stop = 1, .parity = 'n', .phys = &saturnphysuart, .special = 0, },};static void suinterrupt(Ureg*, void*);static Uart*supnp(void){ int i; for (i = 0; i < nelem(suart)-1; i++) suart[i].next = &suart[i + 1]; suart[nelem(suart)-1].next=nil; return suart;}static voidsuinit(Uart*uart){ UartData *ud; Saturnuart *su; ud = uart->regs; su = ud->su; su->fcr=Fcr_txreset|Fcr_rxreset; ud->initialized=1;}static voidsuenable(Uart*uart, int ie){ Saturnuart *su; UartData *ud; int nr; nr = uart - suart; if (nr < 0 || nr > Nuart) panic("No uart %d", nr); ud = uartdata + nr; ud->suno = nr; su=ud->su = (Saturnuart*)((nr == 0)? UartAoffs: UartBoffs); uart->regs = ud; if(ud->initialized==0) suinit(uart); if(!ud->enabled && ie){ intrenable(Vecuart0+nr , suinterrupt, uart, uart->name); su->ier=Ier_txempty|Ier_rxfull; ud->enabled=1; }}static longsustatus(Uart* uart, void* buf, long n, long offset){ Saturnuart *su; char p[128]; su = ((UartData*)uart->regs)->su; snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n" "dev(%d) type(%d) framing(%d) overruns(%d)\n", uart->baud, uart->hup_dcd, uart->hup_dsr, Txsize, (su->lcr & Lcr_pen)? ((su->lcr & Lcr_peven) ? 'e': 'o'): 'n', (su->lcr & Lcr_stop)? 2: 1, uart->dev, uart->type, uart->ferr, uart->oerr); n = readstr(offset, buf, n, p); free(p); return n;}static voidsufifo(Uart*, int){}static voidsudtr(Uart*, int){}static voidsurts(Uart*, int){}static voidsumodemctl(Uart*, int){}static intsuparity(Uart*uart, int parity){ int lcr; Saturnuart *su; su = ((UartData*)uart->regs)->su; lcr = su->lcr & ~(Lcr_pen|Lcr_peven); switch(parity){ case 'e': lcr |= (Lcr_pen|Lcr_peven); break; case 'o': lcr |= Lcr_pen; break; case 'n': default: break; } su->lcr = lcr; uart->parity = parity; return 0;}static intsustop(Uart* uart, int stop){ int lcr; Saturnuart *su; su = ((UartData*)uart->regs)->su; lcr = su->lcr & ~Lcr_stop; switch(stop){ case 1: break; case 2: lcr |= Lcr_stop; break; default: return -1; } /* Set new value and reenable if device was previously enabled */ su->lcr = lcr; uart->stop = stop; return 0;}static intsubits(Uart*uart, int n){ Saturnuart *su; uchar lcr; su = ((UartData*)uart->regs)->su; if(n<5||n>8) return -1; lcr = su->lcr & ~Lcr_wrdlenmask; lcr |= (n-5) << Lcr_wrdlenshift; su->lcr = lcr; return 0;}static intsubaud(Uart* uart, int baud){ ushort v; Saturnuart *su; if (uart->enabled){ su = ((UartData*)uart->regs)->su; if(baud <= 0) return -1; v = Baudfreq / baud; su->lcr |= Lcr_div; su->dll = v; su->dlm = v >> 8; su->lcr &= ~Lcr_div; } uart->baud = baud; return 0;}static voidsubreak(Uart*, int){}static voidsukick(Uart *uart){ Saturnuart *su; int i; if(uart->blocked) return; su = ((UartData*)uart->regs)->su; if((su->iir & Iir_txempty) == 0) return; for(i = 0; i < Txsize; i++){ if(uart->op >= uart->oe && uartstageoutput(uart) == 0) break; su->txb = *(uart->op++); su->ier |= Ier_txempty; break; }}static voidsuputc(Uart *uart, int c){ Saturnuart *su; su = ((UartData*)uart->regs)->su; while((su->lsr&Lsr_tbre) == 0) ; su->txb=c; while((su->lsr&Lsr_tbre) == 0) ;}static intgetchars(Uart *uart, uchar *cbuf){ int nc; UartData *ud; Saturnuart *su; ud = uart->regs; su = ud->su; while((su->lsr&Lsr_rxavail) == 0) ; *cbuf++ = su->rxb; nc = 1; while(su->lsr&Lsr_rxavail){ *cbuf++ = su->rxb; nc++; } return nc;}static intsugetc(Uart *uart){ static uchar buf[128], *p; static int cnt; char c; if (cnt <= 0) { cnt = getchars(uart, buf); p = buf; } c = *p++; cnt--; return c;}static voidsuinterrupt(Ureg*, void*u){ Saturnuart *su; Uart *uart; uchar iir; uart = u; if (uart == nil) panic("uart is nil"); su = ((UartData*)uart->regs)->su; iir = su->iir; if(iir&Iir_rxfull) while(su->lsr&Lsr_rxavail) uartrecv(uart, su->rxb); if(iir & Iir_txempty){ su->ier&=~Ier_txempty; uartkick(uart); } if (iir & Iir_rxerr) uart->oerr++; intack();}static voidsudisable(Uart* uart){ Saturnuart *su; su = ((UartData*)uart->regs)->su; su->ier&=~(Ier_txempty|Ier_rxfull);}PhysUart saturnphysuart = { .name = "su", .pnp = supnp, .enable = suenable, .disable = sudisable, .kick = sukick, .dobreak = subreak, .baud = subaud, .bits = subits, .stop = sustop, .parity = suparity, .modemctl = sumodemctl, .rts = surts, .dtr = sudtr, .status = sustatus, .fifo = sufifo, .getc = sugetc, .putc = suputc,};voidconsole(void){ Uart *uart; int n; char *cmd, *p; if((p = getconf("console")) == nil) return; n = strtoul(p, &cmd, 0); if(p == cmd) return; if(n < 0 || n >= nelem(suart)) return; uart = suart + n;/* uartctl(uart, "b115200 l8 pn s1"); */ if(*cmd != '\0') uartctl(uart, cmd); (*uart->phys->enable)(uart, 0); consuart = uart; uart->console = 1;} Saturnuart*uart = (Saturnuart*)UartAoffs;voiddbgputc(int c){ while((uart->lsr&Lsr_tbre) == 0) ; uart->txb=c; while((uart->lsr&Lsr_tbre) == 0) ;}voiddbgputs(char*s){ while(*s) dbgputc(*s++);}voiddbgputx(ulong x){ int i; char c; for(i=0; i < sizeof(ulong) * 2; i++){ c = ((x >> (28 - i * 4))) & 0xf; if(c >= 0 && c <= 9) c += '0'; else c += 'a' - 10; while((uart->lsr&Lsr_tbre) == 0) ; uart->txb=c; } while((uart->lsr&Lsr_tbre) == 0) ; uart->txb='\n'; while((uart->lsr&Lsr_tbre) == 0) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -