Coherent4.2.10/io.386/albaud.c
/* $Header: /ker/io.386/RCS/albaud.c,v 2.4 93/10/29 00:58:25 nigel Exp Locker: nigel $ */
/*
* Purpose: common code for various async drivers
*
* $Log: albaud.c,v $
* Revision 2.4 93/10/29 00:58:25 nigel
* R98 (aka 4.2 Beta) prior to removing System Global memory
*
* Revision 2.3 93/08/19 04:02:04 nigel
* Nigel's R83
*
* Revision 2.2 93/07/26 15:27:51 nigel
* Nigel's R80
*
* Revision 1.2 93/04/14 10:24:08 root
* r75
*
* Revision 1.1 92/04/30 08:58:54 hal
* Add asy. Remove silos from tty struct.
*/
#include <kernel/param.h>
#include <sys/ins8250.h>
#define TESTBAUD 0x03A5
int uart_sense();
int albaud[] ={
0, /* 0 */
2304, /* 50 */
1536, /* 75 */
1047, /* 110 */
857, /* 134.5 */
768, /* 150 */
576, /* 200 */
384, /* 300 */
192, /* 600 */
96, /* 1200 */
64, /* 1800 */
#ifdef _I386
48, /* 2400 */
24, /* 4800 */
12, /* 9600 */
6, /* 19200 */
3 /* 38400 */
#else
58, /* 2000 */
48, /* 2400 */
32, /* 3600 */
24, /* 4800 */
16, /* 7200 */
12, /* 9600 */
6, /* 19200 */
0, /* EXTA */
0 /* EXTB */
#endif
};
/*
* alp_rate[] is tied to albaud[] - it gives the minimum polling
* rate for the corresponding port speed; it must be a multiple
* of 100 (system clock Hz) and >= baud/6
*/
int alp_rate[] ={ /* baud/6 or zero */
0, /* 0 */
1*HZ, /* 50 */
1*HZ, /* 75 */
1*HZ, /* 110 */
1*HZ, /* 134.5 */
1*HZ, /* 150 */
1*HZ, /* 200 */
1*HZ, /* 300 */
1*HZ, /* 600 */
2*HZ, /* 1200 */
3*HZ, /* 1800 */
#ifdef _I386
4*HZ, /* 2400 */
8*HZ, /* 4800 */
16*HZ, /* 9600 */
32*HZ, /* 19200 */
64*HZ /* 38400 */
#else
4*HZ, /* 2000 */
4*HZ, /* 2400 */
6*HZ, /* 3600 */
8*HZ, /* 4800 */
12*HZ, /* 7200 */
16*HZ, /* 9600 */
32*HZ, /* 19200 */
0, /* EXTA */
0 /* EXTB */
#endif
};
/*
* uart_sense()
*
* Given port address, return what type of 8250-family chip is found there.
*
* 0 - no chip
* 1 - 8250 or 8250B
* 2 - 8250A or 16450
* 3 - 16550
* 4 - 16550A
*
* Only the last of these has usable on-chip FIFO.
*/
int uart_sense(port)
int port;
{
int ret = US_NONE;
unsigned ch;
short testbaud;
char lcr, dll, dlh;
#if 0
/*
* Late in '93, apparently, Natl. Semiconductor started
* making 16550's that don't follow their own spec of
* xx00 xxxx in IIR. So, this part of test for UART
* present is conditioned out, but may still be of
* interest.
*/
/*
* See if UART is detected at port address.
* UART should have IER = 0000 xxxx
* MCR = 000x xxxx
* IIR = xx00 xxxx
* and should be write and read back the baud rate regs.
*/
if (inb(port+IER) & 0xF0
|| inb(port+MCR) & 0xE0
|| inb(port+IIR) & 0x30) {
goto done;
}
#endif
lcr = inb(port + LCR);
outb(port+LCR, LC_DLAB);
dll = inb(port + DLL);
dlh = inb(port + DLH);
outb(port+DLL, TESTBAUD & 0xFF);
outb(port+DLH, TESTBAUD >> 8);
testbaud = inb(port+DLL) | inb(port+DLH) << 8;
outb(port+LCR, LC_CS8);
if (testbaud != TESTBAUD){
goto done;
} else {
outb(port+LCR, LC_DLAB);
outb(port+DLL, dll);
outb(port+DLH, dlh);
outb(port+LCR, lcr);
}
/*
* Scratch register NOT found on 8250/8250B.
*/
outb(port+SCR, 0x55);
ch = inb(port+SCR);
if (ch != 0x55) {
ret = US_8250;
}
/*
* After trying to turn on FIFO mode,
* If IIR is 00xx xxxx, it's 8250A/16450 (no FIFO).
* If IIR is 10xx xxxx, it's 16550 (broken FIFO).
* If IIR is 11xx xxxx, it's 16550A (usable FIFO).
*/
outb(port+FCR, 0x01);
ch = inb(port+FCR);
switch (ch & 0xC0) {
case 0x00:
if (ret == US_NONE)
ret = US_16450;
break;
case 0x80:
if (ret == US_NONE)
ret = US_16550;
break;
case 0xC0:
ret = US_16550A;
break;
}
outb(port+FCR, 0x00);
done:
switch(port){
case 0x3F8:
printf("com1 ");
break;
case 0x2F8:
printf("com2 ");
break;
case 0x3E8:
printf("com3 ");
break;
case 0x2E8:
printf("com4 ");
break;
}
printf("port %x: ", port);
switch (ret) {
case US_NONE:
printf("no UART ");
break;
case US_8250:
printf("8250/8250B ");
break;
case US_16450:
printf("8250A/16450 ");
break;
case US_16550:
printf("16550 - no FIFO ");
break;
case US_16550A:
printf("16550A - FIFO ");
break;
}
return ret;
}