]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ppc/uartsaturn.c
devmnt: make sure auth chan is on said conection in mntattach()
[plan9front.git] / sys / src / 9 / ppc / uartsaturn.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 #include "msaturn.h"
9
10 enum{
11         UartAoffs = Saturn + 0x0a00,
12         UartBoffs = Saturn + 0x0b00,
13         Nuart = 2,
14
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),
21         Lcr_wrdlenshift = 0,
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),
32         Txsize = 16,
33         Rxsize = 16,
34 };
35
36 typedef struct Saturnuart Saturnuart;
37 struct Saturnuart {
38         uchar   rxb;
39 #define txb     rxb
40 #define dll     rxb
41         uchar   ier;                    // Interrupt enable, divisor latch
42 #define dlm     ier
43         uchar   iir;                    // Interrupt identification, fifo control
44 #define fcr     iir     
45         uchar   lcr;                    // Line control register
46         uchar   f1;             
47         uchar   lsr;                    // Line status register
48         ushort  f2;
49 };
50
51 typedef struct UartData UartData;
52 struct UartData {
53         int                     suno;   /* saturn uart number: 0 or 1 */
54         Saturnuart      *su;
55         char                    *rxbuf;
56         char                    *txbuf;
57         int                     initialized;
58         int                     enabled;
59 } uartdata[Nuart];
60
61 extern PhysUart saturnphysuart;
62
63 Uart suart[Nuart] = {
64         {
65                 .name = "SaturnUart1",
66                 .baud = 19200,
67                 .bits = 8,
68                 .stop = 1,
69                 .parity = 'n',
70                 .phys = &saturnphysuart,
71                 .special = 0,
72         },
73         {
74                 .name = "SaturnUart2",
75                 .baud = 115200,
76                 .bits = 8,
77                 .stop = 1,
78                 .parity = 'n',
79                 .phys = &saturnphysuart,
80                 .special = 0,
81         },
82 };
83
84 static void suinterrupt(Ureg*, void*);
85
86 static Uart*
87 supnp(void)
88 {
89         int i;
90
91         for (i = 0; i < nelem(suart)-1; i++)
92                 suart[i].next = &suart[i + 1];
93         suart[nelem(suart)-1].next=nil;
94         return suart;
95 }
96
97 static void
98 suinit(Uart*uart)
99 {
100         UartData *ud;
101         Saturnuart *su;
102
103         ud = uart->regs;
104         su = ud->su;
105         su->fcr=Fcr_txreset|Fcr_rxreset;
106         ud->initialized=1;
107 }
108
109 static void
110 suenable(Uart*uart, int ie)
111 {
112         Saturnuart *su;
113         UartData *ud;
114         int nr;
115
116         nr = uart - suart;
117         if (nr < 0 || nr > Nuart)
118                 panic("No uart %d", nr);
119         ud = uartdata + nr;
120         ud->suno = nr;
121         su=ud->su = (Saturnuart*)((nr == 0)? UartAoffs: UartBoffs);
122         uart->regs = ud;
123
124         if(ud->initialized==0)
125                 suinit(uart);
126
127         if(!ud->enabled && ie){
128                 intrenable(Vecuart0+nr , suinterrupt, uart, uart->name);
129                 su->ier=Ier_txempty|Ier_rxfull;
130                 ud->enabled=1;
131         }
132 }
133
134
135 static long
136 sustatus(Uart* uart, void* buf, long n, long offset)
137 {
138         Saturnuart *su;
139         char p[128];
140
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",
144
145                 uart->baud,
146                 uart->hup_dcd, 
147                 uart->hup_dsr,
148                 Txsize,
149                 (su->lcr & Lcr_pen)? ((su->lcr & Lcr_peven) ? 'e': 'o'): 'n',
150                 (su->lcr & Lcr_stop)? 2: 1,
151
152                 uart->dev,
153                 uart->type,
154                 uart->ferr,
155                 uart->oerr);
156         n = readstr(offset, buf, n, p);
157         free(p);
158
159         return n;
160 }
161
162 static void
163 sufifo(Uart*, int)
164 {}
165
166 static void
167 sudtr(Uart*, int)
168 {}
169
170 static void
171 surts(Uart*, int)
172 {}
173
174 static void
175 sumodemctl(Uart*, int)
176 {}
177
178 static int
179 suparity(Uart*uart, int parity)
180 {
181         int lcr;
182         Saturnuart *su;
183
184         su = ((UartData*)uart->regs)->su;
185
186         lcr = su->lcr & ~(Lcr_pen|Lcr_peven);
187
188         switch(parity){
189         case 'e':
190                 lcr |= (Lcr_pen|Lcr_peven);
191                 break;
192         case 'o':
193                 lcr |= Lcr_pen;
194                 break;
195         case 'n':
196         default:
197                 break;
198         }
199
200         su->lcr = lcr;
201         uart->parity = parity;
202
203         return 0;
204 }
205
206 static int
207 sustop(Uart* uart, int stop)
208 {
209         int lcr;
210         Saturnuart *su;
211
212         su = ((UartData*)uart->regs)->su;
213         lcr = su->lcr & ~Lcr_stop;
214
215         switch(stop){
216         case 1:
217                 break;
218         case 2:
219                 lcr |= Lcr_stop;
220                 break;
221         default:
222                 return -1;
223         }
224
225         /* Set new value and reenable if device was previously enabled */
226         su->lcr = lcr;
227         uart->stop = stop;
228
229         return 0;
230 }
231
232 static int
233 subits(Uart*uart, int n)
234 {       
235         Saturnuart *su;
236         uchar lcr;
237
238         su = ((UartData*)uart->regs)->su;
239         if(n<5||n>8)
240                 return -1;
241
242         lcr = su->lcr & ~Lcr_wrdlenmask;
243         lcr |= (n-5) << Lcr_wrdlenshift;
244         su->lcr = lcr;
245         return 0;
246 }
247
248 static int
249 subaud(Uart* uart, int baud)
250 {
251         ushort v;
252         Saturnuart *su;
253
254         if (uart->enabled){
255                 su = ((UartData*)uart->regs)->su;
256         
257                 if(baud <= 0)
258                         return -1;
259
260                 v = Baudfreq / baud;
261                 su->lcr |= Lcr_div;
262                 su->dll = v;
263                 su->dlm = v >> 8;
264                 su->lcr &= ~Lcr_div;
265         }
266         uart->baud = baud;
267
268         return 0;
269 }
270
271 static void
272 subreak(Uart*, int)
273 {}
274
275 static void
276 sukick(Uart *uart)
277 {
278         Saturnuart *su;
279         int i;
280
281         if(uart->blocked)
282                 return;
283
284         su = ((UartData*)uart->regs)->su;
285         if((su->iir & Iir_txempty) == 0)
286                 return;
287
288         for(i = 0; i < Txsize; i++){
289                 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
290                         break;
291                 su->txb = *(uart->op++);
292                 su->ier |= Ier_txempty;
293                 break;
294         }
295 }
296
297 static void
298 suputc(Uart *uart, int c)
299 {
300         Saturnuart *su;
301
302         su = ((UartData*)uart->regs)->su;
303         while((su->lsr&Lsr_tbre) == 0)
304                 ;
305
306         su->txb=c;
307         while((su->lsr&Lsr_tbre) == 0)
308                         ;
309 }
310
311 static int
312 getchars(Uart *uart, uchar *cbuf)
313 {
314         int nc;
315         UartData *ud;
316         Saturnuart *su;
317
318         ud = uart->regs;
319         su = ud->su;
320
321         while((su->lsr&Lsr_rxavail) == 0)
322                 ;
323
324         *cbuf++ = su->rxb;
325         nc = 1;
326         while(su->lsr&Lsr_rxavail){
327                 *cbuf++ = su->rxb;
328                 nc++;
329         }
330         return nc;
331 }
332
333 static int
334 sugetc(Uart *uart)
335 {
336         static uchar buf[128], *p;
337         static int cnt;
338         char    c;
339
340         if (cnt <= 0) {
341                 cnt = getchars(uart, buf);
342                 p = buf;
343         }
344         c = *p++;
345         cnt--;
346         return c;
347 }
348
349 static void
350 suinterrupt(Ureg*, void*u)
351 {
352         Saturnuart *su;
353         Uart *uart;
354         uchar iir;
355
356         uart = u;
357         if (uart == nil)
358                 panic("uart is nil");
359         su = ((UartData*)uart->regs)->su;
360         iir = su->iir;
361         if(iir&Iir_rxfull)
362                 while(su->lsr&Lsr_rxavail)
363                         uartrecv(uart, su->rxb);
364         if(iir & Iir_txempty){
365                 su->ier&=~Ier_txempty;
366                 uartkick(uart);
367         }
368         if (iir & Iir_rxerr)
369                 uart->oerr++;
370         intack();
371 }
372
373 static void
374 sudisable(Uart* uart)
375 {
376         Saturnuart *su;
377
378         su = ((UartData*)uart->regs)->su;
379         su->ier&=~(Ier_txempty|Ier_rxfull);
380 }
381
382 PhysUart saturnphysuart = {
383         .name           = "su",
384         .pnp                    = supnp,
385         .enable         = suenable,
386         .disable                = sudisable,
387         .kick                   = sukick,
388         .dobreak                = subreak,
389         .baud           = subaud,
390         .bits                   = subits,
391         .stop                   = sustop,
392         .parity         = suparity,
393         .modemctl       = sumodemctl,
394         .rts                    = surts,
395         .dtr                    = sudtr,
396         .status         = sustatus,
397         .fifo                   = sufifo,
398         .getc                   = sugetc,
399         .putc                   = suputc,
400 };
401
402 void
403 console(void)
404 {
405         Uart *uart;
406         int n;
407         char *cmd, *p;
408
409         if((p = getconf("console")) == nil)
410                 return;
411         n = strtoul(p, &cmd, 0);
412         if(p == cmd)
413                 return;
414         if(n < 0 || n >= nelem(suart))
415                 return;
416
417         uart = suart + n;
418
419 /*      uartctl(uart, "b115200 l8 pn s1"); */
420         if(*cmd != '\0')
421                 uartctl(uart, cmd);
422         (*uart->phys->enable)(uart, 0);
423
424         consuart = uart;
425         uart->console = 1;
426
427
428 Saturnuart*uart = (Saturnuart*)UartAoffs;
429
430 void
431 dbgputc(int c)
432 {
433         while((uart->lsr&Lsr_tbre) == 0)
434                 ;
435
436         uart->txb=c;
437         while((uart->lsr&Lsr_tbre) == 0)
438                         ;
439 }
440
441 void
442 dbgputs(char*s)
443 {
444         while(*s)
445                 dbgputc(*s++);
446 }
447
448 void
449 dbgputx(ulong x)
450 {
451         int i;
452         char c;
453
454         for(i=0; i < sizeof(ulong) * 2; i++){
455                 c = ((x >> (28 - i * 4))) & 0xf;
456                 if(c >= 0 && c <= 9)
457                         c += '0';
458                 else
459                         c += 'a' - 10;
460
461                 while((uart->lsr&Lsr_tbre) == 0)
462                         ;
463
464                 uart->txb=c;
465         }
466         while((uart->lsr&Lsr_tbre) == 0)
467                         ;
468
469         uart->txb='\n';
470         while((uart->lsr&Lsr_tbre) == 0)
471                         ;
472 }