⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m16c552.cpp

📁 16c552源代码
💻 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 + -