📄 p3544sio.c
字号:
/* p3544Sio.c - p3544 serial driver *//* Copyright 1984-2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01k,05dec00,dat merge from sustaining branch to tor2_0_x01j,20nov00,pai enabled receiver buffer full interrupt from UART in p3544Startup() (SPR 32443).01i,06oct99,pai account for PC87307 hardware anomaly in p3544Int() (SPR 26117).01h,26oct98,dbt call p3544InitChannel() in p3544HrdInit() rather than in p3544ModeSet(). (SPR #22349).01g,23may97,db added hardware options and modem control(SPR #7542). fixed bugs reported in SPRs 9404, 9223.01f,12oct95,dgf added bauds > 38k01e,03aug95,myz fixed the warning messages01d,12jul95,myz fixed the baud rate problem.01c,20jun95,ms fixed comments for mangen.01b,15jun95,ms updated for new driver structure01a,15mar95,myz written (using p3544Serial.c + the VxMon polled driver).*//*DESCRIPTIONThis is the driver for the cPCI 3544 UART Chip used on the PC 386.It uses the SCCs in asynchronous mode only.USAGEAn p3544_CHAN structure is used to describe the chip.The BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the register values in the p3544_CHAN structure(except the SIO_DRV_FUNCS) before calling p3544HrdInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chips interrupt handler (p3544Int) via intConnect().IOCTL FUNCTIONSThis driver responds to all the same ioctl() codes as a normal serial driver;for more information, see the comments in sioLib.h. As initialized, theavailable baud rates are 110, 300, 600, 1200, 2400, 4800, 9600, 19200, and38400.This driver handles setting of hardware options such as parity(odd, even) andnumber of data bits(5, 6, 7, 8). Hardware flow control is provided with thehandshakes RTS/CTS. The function HUPCL(hang up on last close) is available.INCLUDE FILES: drv/sio/p3544Sio.h*/#include "vxWorks.h"#include "iv.h"#include "intLib.h"#include "errnoLib.h"#include "p3544Sio.h"#include "logLib.h"#include <ioLib.h>#include <stdio.h>#include <string.h>#include <vxWorks.h>#include <taskLib.h>/* defines *//* This value is used to specify the maximum number of times p3544Int() * routine will read the 3544 Interrupt Identification Register before * returning. This value should optimally be derived from the BRDR. */LOCAL char *Hwa_PCI3544_Rec_Data_Buffer_char[8*4];LOCAL void Hwa_CPCI_3544_Rec_Task_Func(UINT8 Inser_Para_Fd );LOCAL int Hwa_Cpci_3544_Task_Id[4];#define ASTD_COM_FLAGS (ASYNC_BOOT_AUTOCONF |ASYNC_AUTO_IRQ )#define p3544_IIR_READ_MAX 40#ifndef p3544_DEFAULT_BAUD# define p3544_DEFAULT_BAUD 9600#endif#ifndef SIO_HUP# define SIO_OPEN 0x100A# define SIO_HUP 0x100B#endif/* locals *//* baudTable is a table of the available baud rates, and the values to write * to the UART's baud rate divisor {high, low} register. the formula is * 1843200(source) / (16 * baudrate) */static p3544_BAUD p3544baudTable [] = { {50, 2304}, {75, 1536}, {110, 1047}, {134, 857}, {150, 768}, {300, 384}, {600, 192}, {1200, 96}, {2000, 58}, {2400, 48}, {3600,32}, {4800, 24}, {7200,16}, {9600, 12}, {19200, 6}, {38400, 3}, {57600, 2}, {115200, 1} };static SIO_DRV_FUNCS p3544SioDrvFuncs;static struct serial_uart_config p3544_uart_config[] = { { "unknown", 1, 0 }, { "8250", 1, 0 }, { "16450", 1, 0 }, { "16550", 1, 0 }, { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, { "cirrus", 1, 0 }, { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, { 0, 0}};/* forward declarations */LOCAL void p3544InitChannel (p3544_CHAN *);LOCAL int p3544Ioctl(p3544_CHAN *, int, int);LOCAL int p3544Startup(p3544_CHAN *pChan);LOCAL int p3544PRxChar (p3544_CHAN *pChan, char *ch);LOCAL int p3544PTxChar(p3544_CHAN *pChan, char ch);LOCAL STATUS p3544OptsSet (p3544_CHAN *, UINT);LOCAL STATUS p3544ModeSet (p3544_CHAN *, UINT);LOCAL STATUS p3544BaudSet (p3544_CHAN *, UINT);LOCAL void p3544_check_modem_status(p3544_CHAN * pChan);LOCAL void p3544_autoconfig( p3544_CHAN * pChan);/*************Add Dengtao 2005-09-27*****************/LOCAL BOOL Hwa_Cpci_3544_Inst=FALSE;/******************************************************************************** p3544CallbackInstall ( ) - install ISR callbacks to get put chars.** This routine installs the callback functions for the driver** RETURNS: OK on success or ENOSYS on unsupported callback type.*/ static int p3544CallbackInstall ( SIO_CHAN * pSioChan, int callbackType, STATUS (*callback)(), void * callbackArg ) { p3544_CHAN * pChan = (p3544_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = callback; pChan->putRcvArg = callbackArg; return (OK); default: return (ENOSYS); } }/******************************************************************************** p3544HrdInit () - initialize the chip** This routine is called to reset the chip in a quiescent state.* RETURNS: N/A*/void p3544HrdInit ( p3544_CHAN * pChan /* pointer to device */ ) { if (p3544SioDrvFuncs.ioctl == NULL) { p3544SioDrvFuncs.ioctl = (int (*)())p3544Ioctl; p3544SioDrvFuncs.txStartup = (int (*)())p3544Startup; // p3544SioDrvFuncs.callbackInstall = (int (*)())p3544CallbackInstall; p3544SioDrvFuncs.callbackInstall = p3544CallbackInstall; p3544SioDrvFuncs.pollInput = (int (*)())p3544PRxChar; p3544SioDrvFuncs.pollOutput = (int (*)(SIO_CHAN *,char))p3544PTxChar; } pChan->pDrvFuncs = &p3544SioDrvFuncs; p3544_autoconfig(pChan); /*detect port type */ p3544InitChannel(pChan); /* reset the channel *///printf("sucongna p3544initchannel\t"); }/********************************************************************************* p3544InitChannel () - initialize a single channel*/static void p3544InitChannel ( p3544_CHAN * pChan /* pointer to device */ ) { int intLevel; pChan->options = (CS8 | CREAD | CLOCAL); intLevel = intLock (); if (p3544_uart_config[pChan->port_type].flags & UART_STARTECH) { /* Wake up UART */ PCI_OUT_BYTE(pChan->lcr, 0xBF); PCI_OUT_BYTE(pChan->efr, UART_EFR_ECB); PCI_OUT_BYTE(pChan->ier, 0); PCI_OUT_BYTE(pChan->efr, 0); PCI_OUT_BYTE(pChan->lcr, 0); } if (pChan->port_type == PORT_16750) { /* Wake up UART */ PCI_OUT_BYTE(pChan->ier, 0); } /* * Clear the FIFO buffers and disable them * (they will be reenabled in p220_change_speed()) */ if (p3544_uart_config[pChan->port_type].flags & UART_CLEAR_FIFO) { PCI_OUT_BYTE(pChan->fcr, ((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)));////su } /* set channel baud rate */ p3544OptsSet(pChan, pChan->options );//su (void) p3544BaudSet(pChan, p3544_DEFAULT_BAUD); /* * At this point there's no way the LSR could still be 0xFF; * if it is, then bail out, because there's likely no UART * here. */ if (PCI_IN_BYTE(pChan->lsr) == 0xff) { intUnlock (intLevel); return ; } /* * Clear the interrupt registers. */ (void) PCI_IN_BYTE(pChan->data); (void) PCI_IN_BYTE(pChan->iir); (void) PCI_IN_BYTE(pChan->msr); /* * Now, initialize the UART */ PCI_OUT_BYTE(pChan->lcr, UART_LCR_WLEN8); /* reset DLAB *///su PCI_OUT_BYTE(pChan->mcr, UART_MCR_OUT2); //su /* * Finally, enable interrupts */ PCI_OUT_BYTE(pChan->ier, UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI); /* enable interrupts *///su /* * And clear the interrupt registers again for luck. */ (void)PCI_IN_BYTE(pChan->lsr); (void)PCI_IN_BYTE(pChan->data); (void)PCI_IN_BYTE(pChan->iir); (void)PCI_IN_BYTE(pChan->msr); intUnlock (intLevel); return ; }/********************************************************************************* p3544Hu () - hang up the modem control lines ** Resets the RTS and DTR signals.** RETURNS: OK*/LOCAL STATUS p3544Hup ( p3544_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ oldlevel = intLock (); PCI_OUT_BYTE (pChan->mcr, UART_MCR_OUT2); intUnlock (oldlevel); return (OK); } /********************************************************************************* p3544Open () - Set the modem control lines ** Set the modem control lines(RTS, DTR) TRUE if not already set. * It also clears the receiver. ** RETURNS: OK*/LOCAL STATUS p3544Open ( p3544_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ char mask; /* read modem control register */ mask = (PCI_IN_BYTE (pChan->mcr)) & (UART_MCR_RTS | UART_MCR_DTR); if (mask != (UART_MCR_RTS | UART_MCR_DTR)) { /* RTS and DTR not set yet */ oldlevel = intLock (); /* set RTS and DTR TRUE */ PCI_OUT_BYTE (pChan->mcr, (UART_MCR_RTS | UART_MCR_DTR | \ UART_MCR_OUT2)); intUnlock (oldlevel); } return (OK); }/******************************************************************************** p3544BaudSet () - change baud rate for channel** This routine sets the baud rate for the UART. The interrupts are disabled* during chip access.** RETURNS: OK to indicate success, otherwise ERROR is returned*/LOCAL STATUS p3544BaudSet ( p3544_CHAN * pChan, /* pointer to channel */ UINT baud /* requested baud rate */ ) { int oldlevel; STATUS status; FAST int ix; UINT8 lcr,fcr = 0; /* disable interrupts during chip access */ oldlevel = intLock (); status = ERROR; for (ix = 0; ix < NELEMENTS (p3544baudTable); ix++) { if (p3544baudTable [ix].rate == baud) /* lookup baud rate value */ { lcr = PCI_IN_BYTE (pChan->lcr); /*PCI_OUT_BYTE (pChan->lcr, (char)(UART_LCR_DLAB | lcr)); PCI_OUT_BYTE (pChan->dlm, ((p3544baudTable[ix].preset)>> 8)); PCI_OUT_BYTE (pChan->dll, (p3544baudTable[ix].preset)&0xff); PCI_OUT_BYTE (pChan->lcr, lcr);*/ status = OK; break; } } /* Set up FIFO's */ if (p3544_uart_config[pChan->port_type].flags & UART_USE_FIFO) { if (p3544baudTable[ix].rate < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; } intUnlock(oldlevel); return (status); }/********************************************************************************* p3544ModeSet () - change channel mode setting** This driver supports both polled and interrupt modes and is capable of* switching between modes dynamically. ** If interrupt mode is desired this routine enables the channels receiver and * transmitter interrupts. If the modem control option is TRUE, the Tx interrupt* is disabled if the CTS signal is FALSE. It is enabled otherwise. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -