Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}