Программа для определения типа микросхемы UART
Теперь приведем программу TST_UART, реализующую изложенный алгоритм. В данной программе используются созданные нами функции is_UART_8250() и is_UART_FIFO(). Первая позволяет определить по отсутствию регистра расширения микросхему UART 8250, а вторая по особенностям реализации внутреннего буфера данных различает остальные типы микросхем.
Исходный текст программы TST_UART представлен в листинге 5.1.
Листинг 5.1. Файл TST_UART.C
// Программа определения типа микросхемы UART асинхронного
// последовательного адаптера
#define UART_8250 1
#define UART_16450 2
#define UART_16550 3
#define UART_16550A 4
void main(void) {
// Номер асинхронного порта может быть 0 для COM1
// или 1 для COM2
int port = 0;
int test;
printf("\n(c) Frolov G.V. 1992-1994. "
"Программа определения типа UART\n\n");
printf( "\Введите номер асинхронного"
"порта (COM1 - 0, COM2 - 1):");
scanf( "%d", &port );
if(( port != 0 ) && ( port != 1 )){
printf( "асинхронный порт COM%d не поддерживается\n",
port );
exit( -1 );
}
// Проверяем, является ли микросхема UART - UART 8250
if( is_UART_8250(port) == UART_8250 ) {
printf("Обнаружена микросхема UART 8250\n");
exit(0);
}
// Проверяем другие типы микросхем UART
if(( test = is_UART_FIFO(port) ) == UART_16550A ) {
printf("Обнаружена микросхема UART 16550A\n");
exit(0);
}
else if(test == UART_16550) {
printf("Обнаружена микросхема UART 16550\n");
exit(0);
}
printf("Обнаружена микросхема UART 16450\n");
}
/**
*.Name is_UART_8250
*
*.Descr Функция определяет тип микросхемы,
* используемый данным последовательным асинхронным
* адаптером (UART).
*
*.Proto int is_UART_8250( int port );
*
*.Params int port - номер асинхронного адаптера:
* 0 - COM1, 1 - COM2
*
*.Return Для UART 8250 - возвращает константу UART_8250,
* в остальных случаях возвращает 0
**/
int is_UART_8250( int port ) {
int save_scr, in_scr;
// Сохраняем значения регистра расширения
save_scr = inp( 0x3ff - 0x100 * port );
// Записываем в регистр расширения число 0x5A
outp( 0x3ff - 0x100 * port, 0x5A );
// Считываем регистр расширения
in_scr = inp( 0x3ff - 0x100 * port );
// Сохранилось ли записанное число?
if( in_scr != 0x5A ) {
// Если нет, значит, регистр расширения отсутствует и,
// следовательно, тип микросхемы - UART 8250
// Восстанавливаем значение регистра расширения
outp( 0x3ff - 0x100 * port, save_scr );
return( UART_8250 );
}
// Записываем в регистр расширения другое число - 0xA5
outp( 0x3ff - 0x100 * port, 0xA5 );
// Считываем регистр расширения
in_scr = inp( 0x3ff - 0x100 * port );
// Восстанавливаем значение регистра расширения
outp( 0x3ff - 0x100 * port, save_scr );
// Сохранилось ли записанное число?
if( in_scr != 0xA5 )
// Если нет, регистр расширения отсутствует и,
// следовательно, тип микросхемы - UART 8250
return( UART_8250 );
// В противном случае регистр расширения есть и надо
// выполнить дальнейшее тестирование для определения
// типа UART
return( 0 );
}
/**
*.Name is_UART_FIFO
*
*.Descr Функция определяет тип микросхемы,
* используемой данным последовательным асинхронным
* адаптером (UART).
*
*.Proto int is_UART_FIFO( int port );
*
*.Params int port - номер асинхронного адаптера:
* 0 - COM1, 1 - COM2
*
*.Return для UART 164550 возвращает константу UART_16450,
* для UART 16550 возвращает константу UART_16550,
* для UART 16550A возвращает константу UART_16550A
**/
int is_UART_FIFO( int port ) {
int save_iir, in_iir;
// Сохраняем значение регистра определения прерывания
save_iir = inp( 0x3fa - 0x100 * port );
// Разрешаем использование FIFO
outp( 0x3fa - 0x100 * port, 0x1 );
// Читаем значение регистра определения прерывания
in_iir = inp( 0x3fa - 0x100 * port );
// Восстанавливаем значение регистра определения прерывания
outp( 0x3fa - 0x100 * port, 0x0 );
// Если бит D6 содержит единицу, значит, мы имеем UART 16550A
if(( in_iir & 0x40 ) == 1 )
return( UART_16550A );
// Если бит D7 содержит единицу, значит, мы имеем UART 16550
if(( in_iir & 0x80 ) == 1 )
return( UART_16550 );
// Если биты D7 и D6 содержат нули, значит, мы имеем UART
// 16450 (буфер FIFO отсутствует)
return( UART_16450 );
}