/* port_id.c 1/18/89 Louis Shay National Semiconductor Corporation Microcomuputer Systems Division Microcontroller Applications Group Program to identify the presence and type of UART in a system. This program will query the serial port at global port address "int ubase", and return a value that identifies what type of UART is present at that address. This address is set by the calling program prior to the function call. The returned int values are: 0, if there is no identifiable UART at that port address. 1, if the port type is INS8250, INS8250-B. 2, if the port type is INS8250A, INS82C50A, NS16450, NS16C450. 3, if the port type is NS16550A. 4, if the port type is NS16C552. note: the main source file should include "ns16550a.h". This is the device header file. */ #include #include #include "ns16550a.h" int port_id() { extern int ubase; /* reference global address */ /* 1. test general functionality. Is the core register set present? */ wrLCR( 0xaa ); if( rdLCR() != 0xaa ) /* test LCR register & set DLAB=1 */ return( 0 ); /* as an identifier, UART address 1 is 8-bits (DLM) when LCR7=1 (DLAB). UART address 1 is 4-bits (IER) when DLAB=0. */ wrDLM( 0x55 ); /* test for DLM present (8-bits) */ if( rdDLM() != 0x55 ) return( 0 ); wrLCR( 0x55 ); /* LCR: set DLAB = 0 */ if( rdLCR() != 0x55 ) return( 0 ); wrIER( 0x55 ); /* test for IER present (4-bits) */ if( rdIER() != 0x05 ) return( 0 ); wrFCR( 0 ); /* FIFOs off, if present */ wrIER( 0 ); /* interrupts off, IIR should be 01 */ if( rdIIR() != 1 ) return( 0 ); /* test modem control register address. Should be 5-bits wide */ wrMCR( 0xf5 ); /* 8-bit write */ if( rdMCR() != 0x15 ) /* expect 5-bit read */ return( 0 ); /* test MCR/MSR loopback functions */ wrMCR( 0x10 ); /* set loop mode */ (void)rdMSR(); /* clear out delta bits */ if( ( rdMSR() & 0xf0 ) != 0 ) /* check state bits */ return( 0 ); wrMCR( 0x1f ); /* toggle modem control lines */ if( ( rdMSR() & 0xf0 ) != 0xf0 ) /* check state bits */ return( 0 ); wrMCR( 0x03 ); /* exit loop mode, DTR, RTS active */ /* 2. port id successful at this point. determine port type */ wrSCR( 0x55 ); /* is there a scratch register? */ if( rdSCR() != 0x55 ) return( 1 ); /* no SCR, type = INS8250 */ wrFCR( 0xcf ); /* enable FIFO's, if present */ if( ( rdIIR() & 0xc0 ) != 0xc0 ) /* check FIFO ID bits */ return( 2 ); /* no FIFO's, type = NS16450 */ wrFCR( 0 ); /* turn off FIFO's */ wrLCR( 0x80 ); /* set DLAB */ wrAFR( 0x07 ); /* write to AFR */ if ( rdAFR() != 0x07 ) { /* read AFR */ wrLCR( 0x00 ); /* reset DLAB */ return ( 3 ); /* if not the same, type = NS16550A */ } wrAFR( 0x00); /* clear AFR */ wrLCR( 0x00 ); /* reset DLAB */ return ( 4 ); /* type = NS16C552 */ }