📄 ns16550a.c
字号:
/*
* File: ns16550a.c
* Purpose: Device driver for the NS 16550a UART
*
* Notes:
*
* Author: Eric DeVolder devolder@oakhill.sps.mot.com
* Date: 3-26-96
*
* Modifications:
*
*/
#include "src/uif/dbug.h"
#include "ns16550a.h"
/***********************************************************/
void
ns16550a_init (NS16550A *ns16550a, int baud)
{
/*
* This routine initializes the UART for the specified
* baud and NO interrupts. It also does not enable
* the 16550 FIFOs. (Basically a NS8250 mode device.)
*/
int divisor;
switch (baud)
{
case 19200:
divisor = BPS_19200;
break;
case 38400:
divisor = BPS_38400;
break;
#if (defined(MPC602_EVB))
case 1200:
divisor = BPS_1200;
break;
#endif
case 9600:
default:
divisor = BPS_9600;
break;
}
/*
* Configure the device for 8N1 and also select the
* divisor latches so that divisor can be written to
* them.
*/
ns16550a->LCR = ( 0
| EIGHT_DATA_NO_PARITY_ONE_STOP
| LCR_DLAB
) ;
/*
* Write out the divisor.
*/
ns16550a->BR = (divisor & 0x000000FF); /* DLLSB */
ns16550a->IER = (divisor & 0x0000FF00) >> 8; /* DLMSB */
#if (defined(MPC602_EVB) || defined(MPC602_EVB_NET))
/*
* Put CLK on MF1, programmed in Alternate Function Register
*/
ns16550a->IIR = 0x02;
#endif
/*
* Deselect the divisor latch.
*/
ns16550a->LCR = EIGHT_DATA_NO_PARITY_ONE_STOP;
/*
* Make sure not in 16550 mode, and clear the FIFOs.
*/
ns16550a->IIR = 0;
/*
* If a 16550 device, turn on the FIFO (but not the interrupts)
* so that data won't be lost.
*/
/* ns16550a->IIR =
FCR_FIFO_ENABLE
| FCR_RCVR_FIFO_RESET
| FCR_XMIT_FIFO_RESET
;
*/
/*
* Make sure no interrupts generated.
*/
ns16550a->IER = 0
| IER_ERBFI
;
/*
* Set modem control signals to desired state.
*/
ns16550a->MCR = 0;
/*
* Clear any data which may be incorrectly accumulated.
*/
while (ns16550a->LSR & LSR_DATA_READY)
{
divisor = ns16550a->BR;
}
}
/***********************************************************/
int
ns16550a_in_char (NS16550A *ns16550a)
{
/*
* This routine polls the UART until a character is received.
*/
while (!(ns16550a->LSR & LSR_DATA_READY))
;
return ns16550a->BR;
}
/***********************************************************/
void
ns16550a_out_char (NS16550A *ns16550a, int c)
{
/*
* This routine waits until the UART is ready to transmit, then
* transmits the character.
*/
while (!(ns16550a->LSR & LSR_THR_EMPTY))
;
ns16550a->BR = (BYTE)c;
}
/***********************************************************/
int
ns16550a_char_present (NS16550A *ns16550a)
{
return (ns16550a->LSR & LSR_DATA_READY);
}
/***********************************************************/
int
ns16550a_device_present (NS16550A *ns16550a)
{
/*
* This routine attempts to determine if the 16550a is
* present at the address pointed to by 'ns16550a'.
*/
/*
* 1) Test general functionality of the register set.
*/
ns16550a->LCR = 0xAA;
if (ns16550a->LCR != 0xAA)
{
return -1;
}
/*
* DLM when LCR[7] = 1.
*/
ns16550a->IER = 0x55; /* DLM */
if (ns16550a->IER != 0x55)
{
return -2;
}
ns16550a->LCR = 0x55;
if (ns16550a->LCR != 0x55)
{
return -3;
}
ns16550a->IER = 0x55;
if (ns16550a->IER != 0x05)
{
return -3;
}
ns16550a->IIR = 0x00; /* FCR */
ns16550a->IER = 0x00;
if (ns16550a->IIR != 0x01)
{
return -4;
}
/*
* Test Modem Control registers.
*/
ns16550a->MCR = 0xf5;
if (ns16550a->MCR != 0x15)
{
return -4;
}
ns16550a->MCR = 0x10;
(void)ns16550a->MSR;
if ((ns16550a->MSR & 0xF0) != 0x00)
{
return -5;
}
ns16550a->MCR = 0x1F;
if ((ns16550a->MSR & 0xF0) != 0xF0)
{
return -6;
}
ns16550a->MCR = 0x03;
/*
* Determine port type.
*/
ns16550a->SCR = 0x55;
if (ns16550a->SCR != 0x55)
{
return 1; /* NS8250 */
}
ns16550a->IIR = 0xCF;
if ((ns16550a->IIR & 0xC0) != 0xC0)
{
return 2; /* NS16450 */
}
ns16550a->IIR = 0x00;
ns16550a->LCR = 0x80;
ns16550a->IIR = 0x07;
if (ns16550a->IIR != 0x07)
{
ns16550a->LCR = 0x00;
return 3; /* NS16550A */
}
ns16550a->IIR = 0x00;
ns16550a->LCR = 0x00;
return 4; /* NS16C552 */
}
/***********************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -