2 #include "../port/lib.h"
7 #include "../port/error.h"
11 UartAoffs = Saturn + 0x0a00,
12 UartBoffs = Saturn + 0x0b00,
15 Baudfreq = 14745600 / 16,
16 Lcr_div = RBIT(1, uchar),
17 Lcr_peven = RBIT(3, uchar),
18 Lcr_pen = RBIT(4, uchar),
19 Lcr_stop = RBIT(5, uchar),
20 Lcr_wrdlenmask = RBIT(6, uchar) | RBIT(7, uchar),
22 Lsr_tbre = RBIT(2, uchar),
23 Fcr_txreset = RBIT(5, uchar),
24 Fcr_rxreset = RBIT(6, uchar),
25 Iir_txempty = RBIT(5, uchar),
26 Iir_rxfull = RBIT(6, uchar),
27 Iir_rxerr = RBIT(7, uchar),
28 Ier_rxerr = RBIT(5, uchar),
29 Ier_txempty = RBIT(6, uchar),
30 Ier_rxfull = RBIT(7, uchar),
31 Lsr_rxavail = RBIT(7, uchar),
36 typedef struct Saturnuart Saturnuart;
41 uchar ier; // Interrupt enable, divisor latch
43 uchar iir; // Interrupt identification, fifo control
45 uchar lcr; // Line control register
47 uchar lsr; // Line status register
51 typedef struct UartData UartData;
53 int suno; /* saturn uart number: 0 or 1 */
61 extern PhysUart saturnphysuart;
65 .name = "SaturnUart1",
70 .phys = &saturnphysuart,
74 .name = "SaturnUart2",
79 .phys = &saturnphysuart,
84 static void suinterrupt(Ureg*, void*);
91 for (i = 0; i < nelem(suart)-1; i++)
92 suart[i].next = &suart[i + 1];
93 suart[nelem(suart)-1].next=nil;
105 su->fcr=Fcr_txreset|Fcr_rxreset;
110 suenable(Uart*uart, int ie)
117 if (nr < 0 || nr > Nuart)
118 panic("No uart %d", nr);
121 su=ud->su = (Saturnuart*)((nr == 0)? UartAoffs: UartBoffs);
124 if(ud->initialized==0)
127 if(!ud->enabled && ie){
128 intrenable(Vecuart0+nr , suinterrupt, uart, uart->name);
129 su->ier=Ier_txempty|Ier_rxfull;
136 sustatus(Uart* uart, void* buf, long n, long offset)
141 su = ((UartData*)uart->regs)->su;
142 snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
143 "dev(%d) type(%d) framing(%d) overruns(%d)\n",
149 (su->lcr & Lcr_pen)? ((su->lcr & Lcr_peven) ? 'e': 'o'): 'n',
150 (su->lcr & Lcr_stop)? 2: 1,
156 n = readstr(offset, buf, n, p);
175 sumodemctl(Uart*, int)
179 suparity(Uart*uart, int parity)
184 su = ((UartData*)uart->regs)->su;
186 lcr = su->lcr & ~(Lcr_pen|Lcr_peven);
190 lcr |= (Lcr_pen|Lcr_peven);
201 uart->parity = parity;
207 sustop(Uart* uart, int stop)
212 su = ((UartData*)uart->regs)->su;
213 lcr = su->lcr & ~Lcr_stop;
225 /* Set new value and reenable if device was previously enabled */
233 subits(Uart*uart, int n)
238 su = ((UartData*)uart->regs)->su;
242 lcr = su->lcr & ~Lcr_wrdlenmask;
243 lcr |= (n-5) << Lcr_wrdlenshift;
249 subaud(Uart* uart, int baud)
255 su = ((UartData*)uart->regs)->su;
284 su = ((UartData*)uart->regs)->su;
285 if((su->iir & Iir_txempty) == 0)
288 for(i = 0; i < Txsize; i++){
289 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
291 su->txb = *(uart->op++);
292 su->ier |= Ier_txempty;
298 suputc(Uart *uart, int c)
302 su = ((UartData*)uart->regs)->su;
303 while((su->lsr&Lsr_tbre) == 0)
307 while((su->lsr&Lsr_tbre) == 0)
312 getchars(Uart *uart, uchar *cbuf)
321 while((su->lsr&Lsr_rxavail) == 0)
326 while(su->lsr&Lsr_rxavail){
336 static uchar buf[128], *p;
341 cnt = getchars(uart, buf);
350 suinterrupt(Ureg*, void*u)
358 panic("uart is nil");
359 su = ((UartData*)uart->regs)->su;
362 while(su->lsr&Lsr_rxavail)
363 uartrecv(uart, su->rxb);
364 if(iir & Iir_txempty){
365 su->ier&=~Ier_txempty;
374 sudisable(Uart* uart)
378 su = ((UartData*)uart->regs)->su;
379 su->ier&=~(Ier_txempty|Ier_rxfull);
382 PhysUart saturnphysuart = {
386 .disable = sudisable,
393 .modemctl = sumodemctl,
409 if((p = getconf("console")) == nil)
411 n = strtoul(p, &cmd, 0);
414 if(n < 0 || n >= nelem(suart))
419 /* uartctl(uart, "b115200 l8 pn s1"); */
422 (*uart->phys->enable)(uart, 0);
428 Saturnuart*uart = (Saturnuart*)UartAoffs;
433 while((uart->lsr&Lsr_tbre) == 0)
437 while((uart->lsr&Lsr_tbre) == 0)
454 for(i=0; i < sizeof(ulong) * 2; i++){
455 c = ((x >> (28 - i * 4))) & 0xf;
461 while((uart->lsr&Lsr_tbre) == 0)
466 while((uart->lsr&Lsr_tbre) == 0)
470 while((uart->lsr&Lsr_tbre) == 0)