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