Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * 8250-like UART
3
 */
4
 
5
#include "u.h"
6
#include "../port/lib.h"
7
#include "mem.h"
8
#include "dat.h"
9
#include "fns.h"
10
#include "io.h"
11
 
12
enum {
13
	CONSOLE		= 0,		/* first uart */
14
	Pollstuckoutput	= 1,
15
};
16
 
17
enum {					/* registers */
18
	Rbr		= 0,		/* Receiver Buffer (RO) */
19
	Thr		= 0,		/* Transmitter Holding (WO) */
20
	Ier		= 1,		/* Interrupt Enable */
21
	Iir		= 2,		/* Interrupt Identification (RO) */
22
	Fcr		= 2,		/* FIFO Control (WO) */
23
	Lcr		= 3,		/* Line Control */
24
	Mcr		= 4,		/* Modem Control */
25
	Lsr		= 5,		/* Line Status */
26
	Msr		= 6,		/* Modem Status */
27
 
28
	Scr		= 7,		/* Scratch Pad */
29
//	Mdr		= 8,		/* Mode Def'n (omap rw) */
30
	Usr		= 31,		/* Uart Status Register */
31
	Stickyend,
32
 
33
	Dll		= 0,		/* Divisor Latch LSB */
34
	Dlm		= 1,		/* Divisor Latch MSB */
35
};
36
 
37
enum {					/* Usr */
38
	Busy		= 0x01,
39
};
40
 
41
enum {					/* Ier */
42
	Erda		= 0x01,		/* Enable Received Data Available */
43
	Ethre		= 0x02,		/* Enable Thr Empty */
44
	Erls		= 0x04,		/* Enable Receiver Line Status */
45
	Ems		= 0x08,		/* Enable Modem Status */
46
};
47
 
48
enum {					/* Iir */
49
	Ims		= 0x00,		/* Ms interrupt */
50
	Ip		= 0x01,		/* Interrupt Pending (not) */
51
	Ithre		= 0x02,		/* Thr Empty */
52
	Irda		= 0x04,		/* Received Data Available */
53
	Irls		= 0x06,		/* Receiver Line Status */
54
	Ictoi		= 0x0C,		/* Character Time-out Indication */
55
	IirMASK		= 0x3F,
56
	Ifena		= 0xC0,		/* FIFOs enabled */
57
};
58
 
59
enum {					/* Fcr */
60
	FIFOena		= 0x01,		/* FIFO enable */
61
	FIFOrclr	= 0x02,		/* clear Rx FIFO */
62
	FIFOtclr	= 0x04,		/* clear Tx FIFO */
63
//	FIFOdma		= 0x08,
64
	FIFO1		= 0x00,		/* Rx FIFO trigger level 1 byte */
65
	FIFO4		= 0x40,		/*	4 bytes */
66
	FIFO8		= 0x80,		/*	8 bytes */
67
	FIFO14		= 0xC0,		/*	14 bytes */
68
};
69
 
70
enum {					/* Lcr */
71
	Wls5		= 0x00,		/* Word Length Select 5 bits/byte */
72
	Wls6		= 0x01,		/*	6 bits/byte */
73
	Wls7		= 0x02,		/*	7 bits/byte */
74
	Wls8		= 0x03,		/*	8 bits/byte */
75
	WlsMASK		= 0x03,
76
	Stb		= 0x04,		/* 2 stop bits */
77
	Pen		= 0x08,		/* Parity Enable */
78
	Eps		= 0x10,		/* Even Parity Select */
79
	Stp		= 0x20,		/* Stick Parity */
80
	Brk		= 0x40,		/* Break */
81
	Dlab		= 0x80,		/* Divisor Latch Access Bit */
82
};
83
 
84
enum {					/* Mcr */
85
	Dtr		= 0x01,		/* Data Terminal Ready */
86
	Rts		= 0x02,		/* Ready To Send */
87
	Out1		= 0x04,		/* no longer in use */
88
	Ie		= 0x08,		/* IRQ Enable (cd_sts_ch on omap) */
89
	Dm		= 0x10,		/* Diagnostic Mode loopback */
90
};
91
 
92
enum {					/* Lsr */
93
	Dr		= 0x01,		/* Data Ready */
94
	Oe		= 0x02,		/* Overrun Error */
95
	Pe		= 0x04,		/* Parity Error */
96
	Fe		= 0x08,		/* Framing Error */
97
	Bi		= 0x10,		/* Break Interrupt */
98
	Thre		= 0x20,		/* Thr Empty */
99
	Temt		= 0x40,		/* Transmitter Empty */
100
	FIFOerr		= 0x80,		/* error in receiver FIFO */
101
};
102
 
103
enum {					/* Msr */
104
	Dcts		= 0x01,		/* Delta Cts */
105
	Ddsr		= 0x02,		/* Delta Dsr */
106
	Teri		= 0x04,		/* Trailing Edge of Ri */
107
	Ddcd		= 0x08,		/* Delta Dcd */
108
	Cts		= 0x10,		/* Clear To Send */
109
	Dsr		= 0x20,		/* Data Set Ready */
110
	Ri		= 0x40,		/* Ring Indicator */
111
	Dcd		= 0x80,		/* Carrier Detect */
112
};
113
 
114
enum {					/* Mdr */
115
	Modemask	= 7,
116
	Modeuart	= 0,
117
};
118
 
119
 
120
typedef struct Ctlr {
121
	u32int*	io;
122
	int	irq;
123
	int	tbdf;
124
	int	iena;
125
	int	poll;
126
 
127
	uchar	sticky[Stickyend];
128
 
129
	Lock;
130
	int	hasfifo;
131
	int	checkfifo;
132
	int	fena;
133
} Ctlr;
134
 
135
extern PhysUart i8250physuart;
136
 
137
static Ctlr i8250ctlr[] = {
138
{	.io	= (u32int*)PHYSCONS,
139
	.irq	= ILduart0,
140
	.tbdf	= -1,
141
	.poll	= 0, },
142
};
143
 
144
static Uart i8250uart[] = {
145
{	.regs	= &i8250ctlr[0],
146
	.name	= "cons",
147
	.freq	= 3686000,	/* Not used, we use the global i8250freq */
148
	.phys	= &i8250physuart,
149
	.console= 1,
150
	.next	= nil, },
151
};
152
 
153
#define csr8r(c, r)	((c)->io[r])
154
#define csr8w(c, r, v)	((c)->io[r] = (uchar)((c)->sticky[r] | (v)))
155
#define csr8o(c, r, v)	((c)->io[r] = (uchar)(v))
156
 
157
static long
158
i8250status(Uart* uart, void* buf, long n, long offset)
159
{
160
	char *p;
161
	Ctlr *ctlr;
162
	uchar ier, lcr, mcr, msr;
163
 
164
	ctlr = uart->regs;
165
	p = smalloc(READSTR);
166
	mcr = ctlr->sticky[Mcr];
167
	msr = csr8r(ctlr, Msr);
168
	ier = ctlr->sticky[Ier];
169
	lcr = ctlr->sticky[Lcr];
170
	snprint(p, READSTR,
171
		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
172
		"dev(%d) type(%d) framing(%d) overruns(%d) "
173
		"berr(%d) serr(%d)%s%s%s%s\n",
174
 
175
		uart->baud,
176
		uart->hup_dcd,
177
		(msr & Dsr) != 0,
178
		uart->hup_dsr,
179
		(lcr & WlsMASK) + 5,
180
		(ier & Ems) != 0,
181
		(lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
182
		(mcr & Rts) != 0,
183
		(lcr & Stb) ? 2: 1,
184
		ctlr->fena,
185
 
186
		uart->dev,
187
		uart->type,
188
		uart->ferr,
189
		uart->oerr,
190
		uart->berr,
191
		uart->serr,
192
		(msr & Cts) ? " cts": "",
193
		(msr & Dsr) ? " dsr": "",
194
		(msr & Dcd) ? " dcd": "",
195
		(msr & Ri) ? " ring": ""
196
	);
197
	n = readstr(offset, buf, n, p);
198
	free(p);
199
 
200
	return n;
201
}
202
 
203
static void
204
i8250fifo(Uart* uart, int level)
205
{
206
	Ctlr *ctlr;
207
 
208
	ctlr = uart->regs;
209
	if(ctlr->hasfifo == 0)
210
		return;
211
 
212
	/*
213
	 * Changing the FIFOena bit in Fcr flushes data
214
	 * from both receive and transmit FIFOs; there's
215
	 * no easy way to guarantee not losing data on
216
	 * the receive side, but it's possible to wait until
217
	 * the transmitter is really empty.
218
	 */
219
	ilock(ctlr);
220
	while(!(csr8r(ctlr, Lsr) & Temt))
221
		;
222
 
223
	/*
224
	 * Set the trigger level, default is the max.
225
	 * value.
226
	 * Some UARTs require FIFOena to be set before
227
	 * other bits can take effect, so set it twice.
228
	 */
229
	ctlr->fena = level;
230
	switch(level){
231
	case 0:
232
		break;
233
	case 1:
234
		level = FIFO1|FIFOena;
235
		break;
236
	case 4:
237
		level = FIFO4|FIFOena;
238
		break;
239
	case 8:
240
		level = FIFO8|FIFOena;
241
		break;
242
	default:
243
		level = FIFO14|FIFOena;
244
		break;
245
	}
246
	csr8w(ctlr, Fcr, level);
247
	csr8w(ctlr, Fcr, level);
248
	iunlock(ctlr);
249
}
250
 
251
static void
252
i8250dtr(Uart* uart, int on)
253
{
254
	Ctlr *ctlr;
255
 
256
	/*
257
	 * Toggle DTR.
258
	 */
259
	ctlr = uart->regs;
260
	if(on)
261
		ctlr->sticky[Mcr] |= Dtr;
262
	else
263
		ctlr->sticky[Mcr] &= ~Dtr;
264
	csr8w(ctlr, Mcr, 0);
265
}
266
 
267
static void
268
i8250rts(Uart* uart, int on)
269
{
270
	Ctlr *ctlr;
271
 
272
	/*
273
	 * Toggle RTS.
274
	 */
275
	ctlr = uart->regs;
276
	if(on)
277
		ctlr->sticky[Mcr] |= Rts;
278
	else
279
		ctlr->sticky[Mcr] &= ~Rts;
280
	csr8w(ctlr, Mcr, 0);
281
}
282
 
283
static void
284
i8250modemctl(Uart* uart, int on)
285
{
286
	Ctlr *ctlr;
287
 
288
	ctlr = uart->regs;
289
	ilock(&uart->tlock);
290
	if(on){
291
		ctlr->sticky[Ier] |= Ems;
292
		csr8w(ctlr, Ier, 0);
293
		uart->modem = 1;
294
		uart->cts = csr8r(ctlr, Msr) & Cts;
295
	}
296
	else{
297
		ctlr->sticky[Ier] &= ~Ems;
298
		csr8w(ctlr, Ier, 0);
299
		uart->modem = 0;
300
		uart->cts = 1;
301
	}
302
	iunlock(&uart->tlock);
303
 
304
	/* modem needs fifo */
305
	(*uart->phys->fifo)(uart, on);
306
}
307
 
308
static int
309
i8250parity(Uart* uart, int parity)
310
{
311
	int lcr;
312
	Ctlr *ctlr;
313
 
314
	ctlr = uart->regs;
315
	lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
316
 
317
	switch(parity){
318
	case 'e':
319
		lcr |= Eps|Pen;
320
		break;
321
	case 'o':
322
		lcr |= Pen;
323
		break;
324
	case 'n':
325
		break;
326
	default:
327
		return -1;
328
	}
329
	ctlr->sticky[Lcr] = lcr;
330
	csr8w(ctlr, Lcr, 0);
331
 
332
	uart->parity = parity;
333
 
334
	return 0;
335
}
336
 
337
static int
338
i8250stop(Uart* uart, int stop)
339
{
340
	int lcr;
341
	Ctlr *ctlr;
342
 
343
	ctlr = uart->regs;
344
	lcr = ctlr->sticky[Lcr] & ~Stb;
345
 
346
	switch(stop){
347
	case 1:
348
		break;
349
	case 2:
350
		lcr |= Stb;
351
		break;
352
	default:
353
		return -1;
354
	}
355
	ctlr->sticky[Lcr] = lcr;
356
	csr8w(ctlr, Lcr, 0);
357
 
358
	uart->stop = stop;
359
 
360
	return 0;
361
}
362
 
363
static int
364
i8250bits(Uart* uart, int bits)
365
{
366
	int lcr;
367
	Ctlr *ctlr;
368
 
369
	ctlr = uart->regs;
370
	lcr = ctlr->sticky[Lcr] & ~WlsMASK;
371
 
372
	switch(bits){
373
	case 5:
374
		lcr |= Wls5;
375
		break;
376
	case 6:
377
		lcr |= Wls6;
378
		break;
379
	case 7:
380
		lcr |= Wls7;
381
		break;
382
	case 8:
383
		lcr |= Wls8;
384
		break;
385
	default:
386
		return -1;
387
	}
388
	ctlr->sticky[Lcr] = lcr;
389
	csr8w(ctlr, Lcr, 0);
390
 
391
	uart->bits = bits;
392
 
393
	return 0;
394
}
395
 
396
static int
397
i8250baud(Uart* uart, int baud)
398
{
399
#ifdef notdef				/* don't change the speed */
400
	ulong bgc;
401
	Ctlr *ctlr;
402
	extern int i8250freq;	/* In the config file */
403
 
404
	/*
405
	 * Set the Baud rate by calculating and setting the Baud rate
406
	 * Generator Constant. This will work with fairly non-standard
407
	 * Baud rates.
408
	 */
409
	if(i8250freq == 0 || baud <= 0)
410
		return -1;
411
	bgc = (i8250freq+8*baud-1)/(16*baud);
412
 
413
	ctlr = uart->regs;
414
	while(csr8r(ctlr, Usr) & Busy)
415
		delay(1);
416
	csr8w(ctlr, Lcr, Dlab);		/* begin kludge */
417
	csr8o(ctlr, Dlm, bgc>>8);
418
	csr8o(ctlr, Dll, bgc);
419
	csr8w(ctlr, Lcr, 0);
420
#endif
421
	uart->baud = baud;
422
	return 0;
423
}
424
 
425
static void
426
i8250break(Uart* uart, int ms)
427
{
428
	Ctlr *ctlr;
429
 
430
	if (up == nil)
431
		panic("i8250break: nil up");
432
	/*
433
	 * Send a break.
434
	 */
435
	if(ms <= 0)
436
		ms = 200;
437
 
438
	ctlr = uart->regs;
439
	csr8w(ctlr, Lcr, Brk);
440
	tsleep(&up->sleep, return0, 0, ms);
441
	csr8w(ctlr, Lcr, 0);
442
}
443
 
444
static void
445
emptyoutstage(Uart *uart, int n)
446
{
447
	_uartputs((char *)uart->op, n);
448
	uart->op = uart->oe = uart->ostage;
449
}
450
 
451
static void
452
i8250kick(Uart* uart)
453
{
454
	int i;
455
	Ctlr *ctlr;
456
 
457
	if(/* uart->cts == 0 || */ uart->blocked)
458
		return;
459
 
460
	if(!normalprint) {			/* early */
461
		if (uart->op < uart->oe)
462
			emptyoutstage(uart, uart->oe - uart->op);
463
		while ((i = uartstageoutput(uart)) > 0)
464
			emptyoutstage(uart, i);
465
		return;
466
	}
467
 
468
	/* nothing more to send? then disable xmit intr */
469
	ctlr = uart->regs;
470
	if (uart->op >= uart->oe && qlen(uart->oq) == 0 &&
471
	    (1 || csr8r(ctlr, Lsr) & Temt)) {	/* could try ignoring Temt */
472
		ctlr->sticky[Ier] &= ~Ethre;
473
		csr8w(ctlr, Ier, 0);
474
		return;
475
	}
476
 
477
	/*
478
	 *  128 here is an arbitrary limit to make sure
479
	 *  we don't stay in this loop too long.  If the
480
	 *  chip's output queue is longer than 128, too
481
	 *  bad -- presotto
482
	 */
483
	for(i = 0; i < 128; i++){
484
		if(!(csr8r(ctlr, Lsr) & Thre))
485
			break;
486
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
487
			break;
488
		csr8o(ctlr, Thr, *uart->op++);		/* start tx */
489
		ctlr->sticky[Ier] |= Ethre;
490
		csr8w(ctlr, Ier, 0);			/* intr when done */
491
	}
492
}
493
 
494
void
495
serialkick(void)
496
{
497
	uartkick(&i8250uart[CONSOLE]);
498
}
499
 
500
static Lock i8250intrlock;
501
 
502
static void
503
i8250interrupt(void* arg)
504
{
505
	Ctlr *ctlr;
506
	Uart *uart;
507
	int iir, lsr, old, r;
508
 
509
	uart = arg;
510
	ctlr = uart->regs;
511
	ilock(&i8250intrlock);
512
 
513
	/* force Ethre on.  don't know why this is needed, but it is. */
514
	ctlr->sticky[Ier] |= Ethre;
515
	csr8w(ctlr, Ier, 0);
516
	/* this is probably optional.  maybe it helps fast input. */
517
	ctlr->sticky[Mcr] |= Ie;
518
	csr8w(ctlr, Mcr, 0);
519
 
520
	for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
521
		switch(iir & IirMASK){
522
		case Ims:		/* Ms interrupt */
523
			r = csr8r(ctlr, Msr);
524
			if(r & Dcts){
525
				ilock(&uart->tlock);
526
				old = uart->cts;
527
				uart->cts = r & Cts;
528
				if(old == 0 && uart->cts)
529
					uart->ctsbackoff = 2;
530
				iunlock(&uart->tlock);
531
			}
532
		 	if(r & Ddsr){
533
				old = r & Dsr;
534
				if(uart->hup_dsr && uart->dsr && !old)
535
					uart->dohup = 1;
536
				uart->dsr = old;
537
			}
538
		 	if(r & Ddcd){
539
				old = r & Dcd;
540
				if(uart->hup_dcd && uart->dcd && !old)
541
					uart->dohup = 1;
542
				uart->dcd = old;
543
			}
544
			break;
545
		case Ithre:		/* Thr Empty */
546
			uartkick(uart);
547
			break;
548
		case Irda:		/* Received Data Available */
549
		case Irls:		/* Receiver Line Status */
550
		case Ictoi:		/* Character Time-out Indication */
551
			/*
552
			 * Consume any received data.
553
			 * If the received byte came in with a break,
554
			 * parity or framing error, throw it away;
555
			 * overrun is an indication that something has
556
			 * already been tossed.
557
			 */
558
			while((lsr = csr8r(ctlr, Lsr)) & Dr){
559
				if(lsr & (FIFOerr|Oe))
560
					uart->oerr++;
561
				if(lsr & Pe)
562
					uart->perr++;
563
				if(lsr & Fe)
564
					uart->ferr++;
565
				r = csr8r(ctlr, Rbr);
566
				if(!(lsr & (Bi|Fe|Pe)))
567
					uartrecv(uart, r);
568
			}
569
			break;
570
 
571
		default:
572
			iprint("weird uart interrupt type %#2.2uX\n", iir);
573
			break;
574
		}
575
	}
576
	iunlock(&i8250intrlock);
577
}
578
 
579
static void
580
i8250disable(Uart* uart)
581
{
582
	Ctlr *ctlr;
583
 
584
	/*
585
	 * Turn off DTR and RTS, disable interrupts and fifos.
586
	 */
587
	(*uart->phys->dtr)(uart, 0);
588
	(*uart->phys->rts)(uart, 0);
589
	(*uart->phys->fifo)(uart, 0);
590
 
591
	ctlr = uart->regs;
592
	ctlr->sticky[Ier] = 0;
593
	csr8w(ctlr, Ier, 0);
594
 
595
	if(ctlr->iena != 0){
596
		/* bad idea if the IRQ is shared */
597
//		introff(1 << (ILshift + ctlr->irq));
598
		ctlr->iena = 0;
599
	}
600
}
601
 
602
static void
603
i8250clock(void)
604
{
605
	i8250interrupt(&i8250uart[CONSOLE]);
606
}
607
 
608
static void
609
i8250enable(Uart* uart, int ie)
610
{
611
	Ctlr *ctlr;
612
 
613
	ctlr = uart->regs;
614
	ctlr->sticky[Lcr] = Wls8;		/* no parity */
615
	csr8w(ctlr, Lcr, 0);
616
 
617
	/*
618
	 * Check if there is a FIFO.
619
	 * Changing the FIFOena bit in Fcr flushes data
620
	 * from both receive and transmit FIFOs; there's
621
	 * no easy way to guarantee not losing data on
622
	 * the receive side, but it's possible to wait until
623
	 * the transmitter is really empty.
624
	 * Also, reading the Iir outwith i8250interrupt()
625
	 * can be dangerous, but this should only happen
626
	 * once, before interrupts are enabled.
627
	 */
628
	ilock(ctlr);
629
	if(!ctlr->checkfifo){
630
		/*
631
		 * Wait until the transmitter is really empty.
632
		 */
633
		while(!(csr8r(ctlr, Lsr) & Temt))
634
			;
635
		csr8w(ctlr, Fcr, FIFOena);
636
		if(csr8r(ctlr, Iir) & Ifena)
637
			ctlr->hasfifo = 1;
638
		csr8w(ctlr, Fcr, 0);
639
		ctlr->checkfifo = 1;
640
	}
641
	iunlock(ctlr);
642
 
643
	/*
644
	 * Enable interrupts and turn on DTR and RTS.
645
	 * Be careful if this is called to set up a polled serial line
646
	 * early on not to try to enable interrupts as interrupt-
647
	 * -enabling mechanisms might not be set up yet.
648
	 */
649
	if(ie){
650
		if(ctlr->iena == 0 && !ctlr->poll){
651
			intrenable(ctlr->irq, i8250interrupt, uart);
652
			ctlr->iena = 1;
653
		}
654
		ctlr->sticky[Ier] = Erda;
655
		ctlr->sticky[Mcr] |= Ie;
656
	}
657
	else{
658
		ctlr->sticky[Ier] = 0;
659
		ctlr->sticky[Mcr] = 0;
660
	}
661
	csr8w(ctlr, Ier, 0);
662
	csr8w(ctlr, Mcr, 0);
663
 
664
	(*uart->phys->dtr)(uart, 1);
665
	(*uart->phys->rts)(uart, 1);
666
 
667
	/*
668
	 * During startup, the i8259 interrupt controller is reset.
669
	 * This may result in a lost interrupt from the i8250 uart.
670
	 * The i8250 thinks the interrupt is still outstanding and does not
671
	 * generate any further interrupts. The workaround is to call the
672
	 * interrupt handler to clear any pending interrupt events.
673
	 * Note: this must be done after setting Ier.
674
	 */
675
	if(ie) {
676
		i8250interrupt(uart);
677
		/*
678
		 * force output to resume if stuck.  shouldn't be needed.
679
		 */
680
		if (Pollstuckoutput)
681
			addclock0link(i8250clock, 10);
682
	}
683
}
684
 
685
static Uart*
686
i8250pnp(void)
687
{
688
	return i8250uart;
689
}
690
 
691
static int
692
i8250getc(Uart* uart)
693
{
694
	Ctlr *ctlr;
695
 
696
	ctlr = uart->regs;
697
	while(!(csr8r(ctlr, Lsr) & Dr))
698
		delay(1);
699
	return csr8r(ctlr, Rbr);
700
}
701
 
702
static void
703
i8250putc(Uart* uart, int c)
704
{
705
	int i, s;
706
	Ctlr *ctlr;
707
 
708
	if (!normalprint) {		/* too early; use brute force */
709
		s = splhi();
710
		while (!(((ulong *)PHYSCONS)[Lsr] & Thre))
711
			;
712
		((ulong *)PHYSCONS)[Thr] = (uchar)c;
713
		splx(s);
714
		return;
715
	}
716
 
717
	ctlr = uart->regs;
718
	s = splhi();
719
	for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 200; i++)
720
		delay(5);
721
	csr8o(ctlr, Thr, c);
722
	for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 200; i++)
723
		delay(5);
724
	splx(s);
725
}
726
 
727
void
728
serialputc(int c)
729
{
730
	i8250putc(&i8250uart[CONSOLE], c);
731
}
732
 
733
void
734
serialputs(char* s, int n)
735
{
736
	_uartputs(s, n);
737
}
738
 
739
#ifdef PLAN9K
740
static void
741
i8250poll(Uart* uart)
742
{
743
	Ctlr *ctlr;
744
 
745
	/*
746
	 * If PhysUart has a non-nil .poll member, this
747
	 * routine will be called from the uartclock timer.
748
	 * If the Ctlr .poll member is non-zero, when the
749
	 * Uart is enabled interrupts will not be enabled
750
	 * and the result is polled input and output.
751
	 * Not very useful here, but ports to new hardware
752
	 * or simulators can use this to get serial I/O
753
	 * without setting up the interrupt mechanism.
754
	 */
755
	ctlr = uart->regs;
756
	if(ctlr->iena || !ctlr->poll)
757
		return;
758
	i8250interrupt(uart);
759
}
760
#endif
761
 
762
PhysUart i8250physuart = {
763
	.name		= "i8250",
764
	.pnp		= i8250pnp,
765
	.enable		= i8250enable,
766
	.disable	= i8250disable,
767
	.kick		= i8250kick,
768
	.dobreak	= i8250break,
769
	.baud		= i8250baud,
770
	.bits		= i8250bits,
771
	.stop		= i8250stop,
772
	.parity		= i8250parity,
773
	.modemctl	= i8250modemctl,
774
	.rts		= i8250rts,
775
	.dtr		= i8250dtr,
776
	.status		= i8250status,
777
	.fifo		= i8250fifo,
778
	.getc		= i8250getc,
779
	.putc		= i8250putc,
780
#ifdef PLAN9K
781
	.poll		= i8250poll,
782
#endif
783
};
784
 
785
static void
786
i8250dumpregs(Ctlr* ctlr)
787
{
788
	int dlm, dll;
789
	int _uartprint(char*, ...);
790
 
791
	csr8w(ctlr, Lcr, Dlab);
792
	dlm = csr8r(ctlr, Dlm);
793
	dll = csr8r(ctlr, Dll);
794
	csr8w(ctlr, Lcr, 0);
795
 
796
	_uartprint("dlm %#ux dll %#ux\n", dlm, dll);
797
}
798
 
799
Uart*	uartenable(Uart *p);
800
 
801
/* must call this from a process's context */
802
int
803
i8250console(void)
804
{
805
	Uart *uart;
806
 
807
	if (up == nil)
808
		return -1;			/* too early */
809
 
810
	uart = &i8250uart[CONSOLE];
811
	if(uartenable(uart) != nil && uart->console){
812
		kbdq = uart->iq;
813
		assert(kbdq);
814
		serialoq = uart->oq;
815
		assert(serialoq);
816
		uart->putc = kbdcr2nl;
817
		uart->opens++;
818
		consuart = uart;
819
		/* up wasn't set when chandevreset ran, so enable it now */
820
		i8250disable(uart);
821
		i8250enable(uart, 1);
822
	}
823
	uartctl(uart, "b115200 l8 pn m0 s1 i128 w100");
824
	return 0;
825
}
826
 
827
void
828
_uartputs(char* s, int n)
829
{
830
	char *e;
831
 
832
	for(e = s+n; s < e; s++){
833
		if(*s == '\n')
834
			i8250putc(&i8250uart[CONSOLE], '\r');
835
		i8250putc(&i8250uart[CONSOLE], *s);
836
	}
837
}
838
 
839
int
840
_uartprint(char* fmt, ...)
841
{
842
	int n;
843
	va_list arg;
844
	char buf[PRINTSIZE];
845
 
846
	va_start(arg, fmt);
847
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
848
	va_end(arg);
849
	_uartputs(buf, n);
850
 
851
	return n;
852
}
853
 
854
void (*lprint)(char *, int) = _uartputs;