FreeBSD/Linux Kernel Cross Reference
sys/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 += '';
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 }
Cache object: 1f1d4d50344d68441e356d445c356e69
|