📄 m16c552.cpp
字号:
#include "system.h"
#include "dbase.h"
#include "m16c55x.h"
#include "Misi.h"
#if (M16C552 == YES)
//1331和1710系统的资源定义
#if (MT_MODULE == MT_DF1331 | MT_MODULE == MT_DF1710 | MT_MODULE == MT_DF1711 | MODULE_TYPE == MOD_GYMMI)
static unsigned long M16c552Base[MAX_16C550_NUM] =
{
PORT_16C55X1_BASE,
PORT_16C55X2_BASE
};
static unsigned long M16c552Vector[MAX_16C550_NUM]=
{
INT_16C55X1,
INT_16C55X2
};
#endif
//1730系统的资源定义
#if (MT_MODULE == MT_DF1730)
#define z1730_SHARE_INT_BASE 0x270030
static unsigned long M16c552Base[MAX_16C550_NUM] =
{
0x270000, //M16C55XA_PORT_BASE,
0X270010 //M16C55XB_PORT_BASE
};
static unsigned long M16c552Vector[MAX_16C550_NUM]=
{
27, //V_SER1,
27 // INT 3
};
#endif
int m16c552_driver_int = 0;
void m16c552_init()
{
ULONG ospl;
int i;
ospl = splx(MAX_ILEV);
if(!m16c552_driver_int)
{
for(i=0; i< 2; i++)
{
/* Disable UART interrupts*/
outportb((ULONG)M16c552Base[i]+IENB, 0);
}
}
m16c552_driver_int = TRUE;
splx(ospl);
}
DWORD m16c552_Open(WORD wPort, TSerialMap portInfo)
{
BYTE tmp;
DWORD dwVector;
DWORD dwBaseAddr;
CSerial* pSerial;
DWORD dwMask;
pSerial = GetSerial(wPort);
if(portInfo.nPort >= MAX_16C550_NUM || pSerial == NULL)
{
LogError("m16c552_Open",FILE_LINE,"port invalidate");
return ERR_SERIAL_CHANNEL;
}
pSerial->m_PortInfo = portInfo;
dwBaseAddr = M16c552Base[portInfo.nPort];//COM1_ADD;
dwVector = M16c552Vector[portInfo.nPort];//V_SER1;
pSerial->m_dwBaseAddr = dwBaseAddr;
pSerial->m_dwVector = dwVector;
#if (MT_MODULE == MT_DF1730)
InstallMisi1730Interrupt();
#elif( (MT_MODULE == MT_GYMMI) && (MODULE_TYPE == MOD_GYMMI) )
if(wPort == 1)
DF_SetIntVector(dwVector,m16c552a_Isr,(DWORD)wPort);
else if(wPort == 2)
DF_SetIntVector(dwVector,m16c552b_Isr,(DWORD)wPort);
#else
DF_SetIntVector(dwVector,m16c552_Isr,(DWORD)wPort);
#endif
dwMask = splx(MAX_ILEV);
outportb(dwBaseAddr + IENB, 0);
m16c552_set_baud(wPort);
m16c552_Modem_Init(wPort);/////初始化RTS and DTR 状态
/*-----------------------------------------------------------------*/
/* Enable the FIFOs with trigger level of character */
/* 判断是否允许FIFO控制,16450 无FIFO, */
/*-----------------------------------------------------------------*/
outportb(dwBaseAddr + FCR, ENABLE_FIFO);
tmp = inportb(dwBaseAddr + IIR);
if((tmp & FIFO_EXIST) == FIFO_EXIST)
outportb(dwBaseAddr + FCR, FIFO_THRES_14 | ENABLE_FIFO);//z接收FIFO设为14
(void)splx(dwMask);
#if(MT_MODULE == MT_DF1730)
EnableMisi1730Interrupt();
#else
DF_EnableInt(dwVector);
#endif
return ERR_SUCCESS;
}
void m16c552_Modem_Init(WORD wPort)
{
CSerial* pSerial;
DWORD dwBaseAddr;
BYTE bMedium;
BYTE bModem;
pSerial = GetSerial(wPort);
if(pSerial == NULL)
return;
dwBaseAddr = pSerial->m_dwBaseAddr;
bMedium = pSerial->m_serialPara.bMedium;
if(GetIdentify() != WM_HOST)
{
if((bMedium == SPMODEM) || (bMedium == RADIO)||(bMedium == PBTELEPHONE))
bModem = OUT2;//|DTR; //z000607 备机初始化时,关闭MISI的W/R,
//使数字猫自动连接到主机。
else
bModem = OUT2|RTS;
outportb(dwBaseAddr + MODCTL, bModem);
}
else
{
if((bMedium == SPMODEM) || (bMedium == RADIO)||(bMedium == PBTELEPHONE))
bModem = OUT2|DTR; //z000607 备机初始化时,关闭MISI的W/R,
//使数字猫自动连接到主机。
else
bModem = OUT2|DTR|RTS;
outportb(dwBaseAddr + MODCTL, bModem);
}
pSerial->m_bTxdMode = bModem;
}
DWORD m16c552_RxInt(WORD wPort, BYTE bFlag)
{
CSerial* pSerial;
DWORD dwMask;
pSerial = CSerial::GetSerial(wPort);
if(pSerial == NULL)
return ERR_SERIAL_CHANNEL;
dwMask = splx(MAX_ILEV);
if(bFlag)
pSerial->m_bIntMode |= RXINT | LSINT;
else
pSerial->m_bIntMode &= ~(RXINT | LSINT);
outportb(pSerial->m_dwBaseAddr + IENB, pSerial->m_bIntMode);
splx(dwMask);
return ERR_SUCCESS;
}
BOOL m16c552_WriteAChar(WORD wPort, BYTE bData)
{
CSerial* pSerial;
DWORD lsr_addr, tx_addr;
pSerial = CSerial::GetSerial(wPort);
if(pSerial == NULL)
return FALSE;
lsr_addr = pSerial->m_dwBaseAddr + LSTAT;
tx_addr = pSerial->m_dwBaseAddr + TX;
outportb(tx_addr, bData);
return TRUE;
}
DWORD m16c552_TxInt(WORD wPort, BYTE bFlag)
{
CSerial* pSerial;
DWORD dwMask;
DWORD lsr_addr, tx_addr;
BYTE bData;
pSerial = CSerial::GetSerial(wPort);
if(pSerial == NULL)
return ERR_SERIAL_CHANNEL;
dwMask = splx(MAX_ILEV);
if(bFlag)
pSerial->m_bIntMode |= TXINT;
else
pSerial->m_bIntMode &= ~TXINT;
outportb(pSerial->m_dwBaseAddr + IENB, pSerial->m_bIntMode);
lsr_addr = pSerial->m_dwBaseAddr + LSTAT;
tx_addr = pSerial->m_dwBaseAddr + TX;
if(bFlag)
{
if(pSerial->ReadFromBuf(bData))
outportb(tx_addr, bData);
}
splx(dwMask);
return ERR_SUCCESS;
}
DWORD m16c552_ModemIn(WORD wPort)
{
CSerial* pSerial;
BYTE bModemRtn, bModemSta;
pSerial = CSerial::GetSerial(wPort);
if(pSerial == NULL)
return ERR_SERIAL_CHANNEL;
bModemRtn = 0;
bModemSta = inportb(pSerial->m_dwBaseAddr + MODSTAT);
if(bModemSta & MOD_CTS)
bModemRtn |= MODEM_CTS;
if(bModemSta & MOD_DCD)
bModemRtn |= MODEM_DCD;
return bModemRtn;
}
DWORD m16c552_ModemOut(WORD wPort, BYTE bOut, BYTE bFlag)
{
CSerial* pSerial;
BYTE bTxdMode;
pSerial = CSerial::GetSerial(wPort);
if(pSerial == NULL)
return ERR_SERIAL_CHANNEL;
bTxdMode = pSerial->m_bTxdMode;
if(bFlag)
{
if(bOut & MODEM_DTR)
bTxdMode |= DTR;
if(bOut & MODEM_RTS)
bTxdMode |= RTS;
}
else
{
if(bOut & MODEM_DTR)
bTxdMode &= ~DTR;
if(bOut & MODEM_RTS)
bTxdMode &= ~RTS;
}
pSerial->m_bTxdMode = bTxdMode;
outportb(pSerial->m_dwBaseAddr + MODCTL, bTxdMode);
return ERR_SUCCESS;
}
void m16c552_Isr(DWORD dwPort)
{
BYTE istat;
DWORD dwIntAddr;
DWORD dwBaseAddr;
CSerial* pSerial;
pSerial = CSerial::GetSerial(dwPort);
if(pSerial == NULL)
return;
dwBaseAddr = pSerial->m_dwBaseAddr;
dwIntAddr = dwBaseAddr + IIR;
while(1)
{
istat = inportb(dwIntAddr);
if(istat & INTR_NOTHING)
break;
switch (istat & INTR_ID_MASK)
{
case INTR_RCV_AVAIL:
case INTR_RCV_ERR:
m16c552_rcv_isr(pSerial);
break;
case INTR_MOD_STAT:
m16c552_mod_isr(pSerial);
break;
case INTR_XMT_EMPT: //02 Txd Buffer Empty
m16c552_txd_isr(pSerial);
break;
default :
break;
}
}
}
void m16c552_rcv_isr(CSerial* pSerial)
{
DWORD lsr_addr, rx_addr;
BYTE data, i = 0;
BYTE lstat;
if(pSerial == NULL)
return;
lsr_addr = pSerial->m_dwBaseAddr + LSTAT;
rx_addr = pSerial->m_dwBaseAddr + RX;
i = 0;
while(1)
{
i++;
lstat = inportb(lsr_addr);
if(lstat & LSR_ERROR)
m16c552_rerr_handle(pSerial);
if(lstat & LSR_DR)
{
data = inportb(rx_addr);
pSerial->WriteToBuf(data);
}
else
break;
if(i > 200)
break;
}
}
void m16c552_txd_isr(CSerial* pSerial)
{
DWORD lsr_addr, tx_addr;
BYTE lstat;
BYTE bData;
if(pSerial == NULL)
return;
lsr_addr = pSerial->m_dwBaseAddr + LSTAT;
tx_addr = pSerial->m_dwBaseAddr + TX;
lstat = 0;
while(pSerial->ReadFromBuf(bData))
{
outportb(tx_addr, bData);
lstat = inportb(lsr_addr);
if(!(lstat & LSR_THRE))//z (trasmitter holding register empty==1)
break;
}
if(!pSerial->GetCanSendNum())/*send buffer is empty */
{
lstat = inportb(lsr_addr);
pSerial->SerialTxdCtr(FALSE);////关闭发送中断
}
}
void m16c552_rerr_handle(CSerial* pSerial)
{
BYTE bTmp;
if(pSerial == NULL)
return;
bTmp = inportb(pSerial->m_dwBaseAddr + RX);
if(bTmp == 1)
bTmp++;
}
void m16c552_mod_isr(CSerial* pSerial)
{
/*-----------------------------------------------------------------*/
/* Read modem status register to clear interrupt */
/*-----------------------------------------------------------------*/
BYTE bTmp;
if(pSerial == NULL)
return;
bTmp = inportb(pSerial->m_dwBaseAddr + MODSTAT);
if(bTmp == 1)
bTmp++;
}
void m16c552_set_baud(DWORD dwPort)
{
/*----------------------------------------------------------------*/
/* Wait for the Xmitter register to empty before changing */
/* baudrate. */
/* Note: Even CTS is low, pc16450/pc16550/pc16552 will stll */
/* send data out, so we will not enter into a infinite */
/* loop even if the remote side is not ready to receive the */
/* data. But we may lose OE/FE/PE and BREAK signal */
/* because we read Line Status register and ignore these */
/* bits in the LSR. This seems not to be critical at */
/* time we are changing the baudrate. */
/*----------------------------------------------------------------*/
CSerial* pSerial;
BYTE t;
DWORD dwDivisor, dwBaudRate, dwMask;
BYTE bBaud;
DWORD dwBaseAddr;
BYTE bLCRMode;
DWORD dwFlags;
pSerial = GetSerial(dwPort);
if(pSerial == NULL)
return;
bBaud = pSerial->m_serialPara.bBaud;
dwBaseAddr = pSerial->m_dwBaseAddr;
dwFlags = pSerial->m_serialPara.dwFlags;
dwMask = splx(MAX_ILEV);
/*-----------------------------------------------------------------*/
/* set character size and parity control bit */
/*-----------------------------------------------------------------*/
switch(pSerial->m_serialPara.bCharSize)
{
case 5:
bLCRMode = LCR_5_BIT_DATA;
break;
case 6:
bLCRMode = LCR_6_BIT_DATA;
break;
case 7:
bLCRMode = LCR_7_BIT_DATA;
break;
case 8:
bLCRMode = LCR_8_BIT_DATA;
break;
default:
bLCRMode = LCR_8_BIT_DATA;
break;
}
if(bLCRMode == LCR_5_BIT_DATA)
bLCRMode |= LCR_1_5_STOP_BIT;
else
{
if(dwFlags & 0x02)//2 stop bits
bLCRMode |= LCR_2_STOP_BIT;
else
bLCRMode |= LCR_1_STOP_BIT;
}
if(dwFlags & 0x04)
{
if(dwFlags & 0x08)///odd parity
bLCRMode |= LCR_ODD_PARITY;
else
bLCRMode |= LCR_EVEN_PARITY;
}
else///no parity
bLCRMode |= LCR_NO_PARITY;
outportb(dwBaseAddr + LINECTL, bLCRMode); /* out of line control register */
////Set baudrate
switch(bBaud)
{
case 0: dwBaudRate = 110; break;
case 1: dwBaudRate = 150; break;
case 2: dwBaudRate = 300; break;
case 3: dwBaudRate = 600; break;
case 4: dwBaudRate = 1200; break;
case 5: dwBaudRate = 2400; break;
case 6: dwBaudRate = 4800; break;
case 7: dwBaudRate = 9600; break;
case 8: dwBaudRate = 19200; break;
case 9: dwBaudRate = 38400; break;
case 10:dwBaudRate = 57600; break;
case 11:dwBaudRate = 115200; break;
default:dwBaudRate = 9600; break;
}
while (!( (t = inportb(dwBaseAddr + LSTAT)) & LSR_TEMT) )
{
;
}
/* 发送器空,不同于发送保持寄存器空 */
dwDivisor = (FREQ_PC16X / dwBaudRate / 16);
t = inportb(dwBaseAddr + LINECTL);
t |= DLA_BIT; /* 0x80, line control register set DLAB bit */
outportb(dwBaseAddr + LINECTL,t);
outportb(dwBaseAddr + DLLO, (char)(dwDivisor & 0xff));
outportb(dwBaseAddr + DLHI, (char)((dwDivisor >> 8) & 0xff));
t = inportb(dwBaseAddr + LINECTL);
t &= ~(DLA_BIT);
outportb(dwBaseAddr + LINECTL, t);
splx(dwMask);
}
#if(MT_MODULE == MT_DF1730)
void InstallMisi1730Interrupt()
{
static int 1730InterruptInstalled=0;
if(1730InterruptInstalled == 0)
{
SysSetVector(M16c552Vector[0], z1730MisiIsr, NORMAL_WRAPPER);
1730InterruptInstalled = 1;
}
}
#endif
#if(MT_MODULE == MT_DF1730)
void EnableMisi1730Interrupt()
{
static int MisiInterruptEnabled = 0;
if(MisiInterruptEnabled == 0)
{
EnableIntrReq(3/*M16c552Vector[0]-24*/);// Port_F_Assign_Reg |= 1<<(irq)
MisiInterruptEnabled = 1;
}
}
#endif
#if(MT_MODULE == MT_DF1730)
static void z1730MisiIsr()
{
DWORD dwMask;
BYTE bFlag;
DWORD dwIntCount;
dwMask = splx(MAX_ILEV);
for(dwIntCount=0; dwIntCount < 100; intcount++)
/* avoid dead loop,if encounter hardware interfere */
{
bFlag = ~(inportb(z1730_SHARE_INT_BASE)); /*读共享中断标志寄存器*/
bFlag &= 0x07; /*清除未用的高五位*/
if(!bFlag)
{
break; /*没有中断标志,退出循环*/
}
else
{
if(bFlag & 0x01)
m16c552_Isr(2); /*z16c552第一通道(com2)产生中断*/
if(bFlag & 0x02)
m16c552_Isr(3); /*z16c552第二通道(com3)发生中断*/
if(bFlag & 0x04)
OnChipInt(0); /*85C30发生中断(com4,com5)*/
}
}
splx(imask);
}
#endif
/*added by zqz 2003/3/18*/
#if(MODULE_TYPE == MOD_GYMMI)
void m16c552a_Isr(DWORD dwPort )
{
m16c552_Isr(1);
}
void m16c552b_Isr(DWORD dwPort)
{
m16c552_Isr(2);
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -