/*
Copyright (C) Magna Carta Software, Inc. 1990. All Rights Reserved
INS8250.C -- Routines specific to the National Semiconductor INS8250 family.
*/
#include <ccttype.h>
#if (defined(MSC) || defined(__WATCOMC__) || defined(__HIGHC__))
#include <conio.h>
#endif
/*
MSC v6.0A bugs force sub-optimization of this file
To see the problem, try $(C_OPT) instead of $(C_OPTR) in large model
*/
#if defined(MSC)
#pragma optimize("e", off)
#endif
/*
ISAUART -- Attempt to recognize the UART type when it is a member of the
INS8250 family.
Return value:
EOF -- not recognized;
0 -- INS8250/INS8250-B;
1 -- INS8250A/NS16450;
2 -- NS16550;
3 -- NS16550A;
*/
short isauart(WORD addr)
{
short old_reg, new_reg;
short ret = 0; /* assume an INS8250/B */
/* CHECK FOR A MEMBER OF THE INS8250 FAMILY BY PUTTING IT INTO LOOPBACK */
old_reg = inp(addr+4); /* save MCR */
outp(addr+4, old_reg | 0X10); /* set loopback on */
inp(addr+6); /* reset delta status */
outp(addr+4, inp(addr+4) | 1); /* set DTR HIGH */
if (!(inp(addr+6) & 0X20)) {
ret = -1; /* DSR not HIGH so not recognized */
outp(addr+4, old_reg); /* restore MCR */
}
else {
outp(addr+4, inp(addr+4) & ~1); /* set DTR LOW */
if ((inp(addr+6) & 0X20)) {
ret = -1; /* DSR not LOW so not recognized */
outp(addr+4, old_reg); /* restore MCR */
}
else {
outp(addr+4, old_reg); /* restore MCR */
/* READ THE SCRATCH REGISTER */
old_reg = (short) inp(addr+7);
outp(addr+7, ~old_reg);
if (((~old_reg) & 0XFF) == inp(addr+7)) {
ret = 1;
outp(addr+7, old_reg);
}
if (ret) {
/* THE UART IS 16450 COMPATIBLE -- CHECK FOR 16550x */
old_reg = inp(addr+2);
if (old_reg & 0X30) ret = -1;
if (ret != -1) {
outp(addr+2, 0X1); /* turn on FIFOs */
new_reg = inp(addr+2);
if (new_reg & 0XC0) ret = (new_reg >> 6) & 0XFF;
}
}
}
}
return (ret);
}