📄 m8260sccsio.c
字号:
M8260_SCC_BD_LEN_OFF), 0x0001);
CACHE_PIPE_FLUSH ();
/*
* buffer address
* Value is offset from the beginning of dual-port RAM.
*/
M8260_SCC_32_WR((pSccChan->pBdBase +
M8260_SCC_RCV_BD_OFF +
M8260_SCC_BD_ADDR_OFF), pSccChan->rcvBufferAddr);
/* set the SCC parameter ram field RBASE */
* pSccChan->pRBASE = 0x00 + (pSccChan->pBdBase - (char *)(pSccChan->immrVal));
/* set up the TRANSMIT buffer descriptors */
/*
* buffer status/control
* Not ready, Wrap, Bit Clear-to-send_report, Interrupt. [0x3800]
* if no Clear-to-send_report, use 0x3000.
*/
M8260_SCC_16_WR((pSccChan->pBdBase +
M8260_SCC_TX_BD_OFF +
M8260_SCC_BD_STAT_OFF), 0x3000);
/* buffer length. 1 byte */
M8260_SCC_16_WR((pSccChan->pBdBase +
M8260_SCC_TX_BD_OFF +
M8260_SCC_BD_LEN_OFF), 0x0001);
/* buffer address */
M8260_SCC_32_WR((pSccChan->pBdBase +
M8260_SCC_TX_BD_OFF +
M8260_SCC_BD_ADDR_OFF), pSccChan->txBufferAddr);
/*
* set the SCC parameter ram field TBASE
* Value is offset from the beginning of dual-port RAM.
*/
* pSccChan->pTBASE = 0x08 + (pSccChan->pBdBase - (char *)(pSccChan->immrVal));
/* disable transmit and receive interrupts */
* pSCCM &= ~(M8260_SCC_UART_SCCX_RX | M8260_SCC_UART_SCCX_TX);
/* program the three SCC mode registers: PSMR, GSMR_H, GSMR_L */
/*
* PSMR (Protocol Specific Mode Register) for SCC
* Normal CTS operation, 8 data bits, 1 stop bit, no parity.
* If use asynchronous flow control(CTS pin connected), set FLC bit
*/
* pPSMR = M8260_SCC_UART_PSMR_CL_8BIT; /* M8260_SCC_UART_PSMR_FLC */
/*
* GSMR_H (General Serial Mode Register for SCC, high word)
* Transmit fifo is 1 byte, receive fifo 8 bits
*/
* pGSMR_H = M8260_SCC_GSMRH_RFW | M8260_SCC_GSMRH_TFL;
/*
* GSMR_L (General Serial Mode Register for SCC, low word)
* Set SCC attributes to standard UART mode, 16x Tx/Rx clock rate,
* disable transmitter and receiver
*/
* pGSMR_L = (M8260_SCC_GSMRL_RDCR_X16 |
M8260_SCC_GSMRL_TDCR_X16 |
M8260_SCC_GSMRL_UART)
& ~
(M8260_SCC_GSMRL_ENT | M8260_SCC_GSMRL_ENR);
/* initialize parameter RAM area for this SCC */
* pRFCR = 0x18; /* supervisor data access */
* pTFCR = 0x18; /* supervisor data access */
* pMRBLR = 1; /* max rx buffer length is 1 byte */
/* initialize some unused parameters in SCC parameter RAM */
* pMAX_IDL = 0x0; /* max idle character */
* pBRKCR = 0x0001; /* number of break characters */
* pPAREC = 0x0; /* received parity errors */
* pFRMEC = 0x0; /* frame errors */
* pNOSEC = 0x0; /* noise errors */
* pBRKEC = 0x0; /* break conditions */
* pUADDR1 = 0x0; /* UART address character 1 */
* pUADDR2 = 0x0; /* UART address character 2 */
* pTOSEQ = 0x0; /* out of sequence character */
* pCHARACTER1 = 0x8000; /* */
* pCHARACTER2 = 0x8000; /* Rx control character 1 ~ 8 */
* pCHARACTER3 = 0x8000; /* All not used */
* pCHARACTER4 = 0x8000;
* pCHARACTER5 = 0x8000;
* pCHARACTER6 = 0x8000;
* pCHARACTER7 = 0x8000;
* pCHARACTER8 = 0x8000;
* pRCCM = 0x0C0FF;
CACHE_PIPE_FLUSH ();
/* wait until the CP is clear */
WAIT_CP_COMPLETE_CMD();
/* Tell CP to initialize tx and rx parameters for SCC */
cpcrVal = (M8260_CPCR_OP (M8260_CPCR_RT_INIT)
| M8260_CPCR_SBC (M8260_CPCR_SBC_SCC1 | (scc * 0x1))
| M8260_CPCR_PAGE (M8260_CPCR_PAGE_SCC1 | (scc * 0x1))
| M8260_CPCR_MCN (M8260_CPCR_MCN_ETH)
| M8260_CPCR_FLG);
M8260_SCC_32_WR (M8260_CPCR (immrVal), cpcrVal);
CACHE_PIPE_FLUSH ();
/* wait until the CP is clear */
WAIT_CP_COMPLETE_CMD();
CACHE_PIPE_FLUSH ();
/* lastly, enable the transmitter and receiver */
* pGSMR_L |= (M8260_SCC_GSMRL_ENT | M8260_SCC_GSMRL_ENR);
CACHE_PIPE_FLUSH ();
intUnlock(oldlevel); /* UNLOCK INTERRUPTS */
}
/*******************************************************************************
*
* m8260SioIoctl - special device control
*
* This routine support device specific ioctl commands, including buad set,
* baud get, mode set, mode get, available mode get, change stop bit.
*
* NOTE
* - According to the manual, PSMR[SL] can be changed on the fly.
*
* RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
* request.
*
*/
LOCAL STATUS m8260SioIoctl
(
M8260_SCC_CHAN * pSccChan, /* device to control */
int request, /* request code */
int arg /* some argument */
)
{
int oldlevel;
STATUS status = OK;
UINT32 immrVal = pSccChan->immrVal; /* holder for the immr value */
UINT8 sccNum = pSccChan->sccNum; /* holder for the scc number */
UINT8 scc = sccNum - 1; /* a convenience */
UINT8 baud = pSccChan->bgrNum - 1;
int baudRate;
VINT16 bdStatus;
VINT32 *pBRGC = (VINT32 *) (immrVal + M8260_BRGC_BASE +
(baud * M8260_BRGC_OFFSET_NEXT_BRGC));
VINT16 *pSCCM = (VINT16 *) (immrVal + M8260_SCC_BASE + M8260_SCCM_OFFSET +
(scc * M8260_SCC_OFFSET_NEXT_SCC));
VINT16 *pSCCE = (VINT16 *) (immrVal + M8260_SCC_BASE + M8260_SCCE_OFFSET +
(scc * M8260_SCC_OFFSET_NEXT_SCC));
VINT16 *pPSMR = (VINT16 *) (immrVal + M8260_SCC_BASE +
(scc * M8260_SCC_OFFSET_NEXT_SCC) +
M8260_PSMR_OFFSET);
switch (request)
{
case SIO_BAUD_SET:
if (arg >= SCC_MIN_BAUD && arg <= SCC_MAX_BAUD)
{
/* calculate proper counter value, then enable BRG */
baudRate = (pSccChan->clockRate + (8 * arg)) / (16 * arg);
if (--baudRate > 0xfff)
*pBRGC = (M8260_BRGC_CD_MASK &
(((baudRate + 8) / 16) << M8260_BRGC_CD_SHIFT)) |
M8260_BRGC_EN | M8260_BRGC_DIV16 ;
else
*pBRGC = (M8260_BRGC_CD_MASK &
(baudRate << 1)) | M8260_BRGC_EN;
pSccChan->baudRate = arg;
}
else
status = EIO;
break;
case SIO_BAUD_GET:
* (int *) arg = pSccChan->baudRate;
break;
case SIO_MODE_SET:
if (!((int) arg == SIO_MODE_POLL || (int) arg == SIO_MODE_INT))
{
status = EIO;
break;
}
/* lock interrupt */
oldlevel = intLock();
/* initialize channel on first MODE_SET */
if (!pSccChan->channelMode)
m8260SioResetChannel(pSccChan);
/*
* if switching from POLL to INT mode, wait for all characters to
* clear the output pins
*/
if ((pSccChan->channelMode == SIO_MODE_POLL) && (arg == SIO_MODE_INT))
{
do
{
M8260_SCC_16_RD((pSccChan->pBdBase +
M8260_SCC_TX_BD_OFF +
M8260_SCC_BD_STAT_OFF), bdStatus);
} while (bdStatus & M8260_SCC_UART_TX_BD_READY);
}
if (arg == SIO_MODE_INT)
{
/* reset the SCC's interrupt status bit */
* M8260_SIPNR_L(immrVal) = pSccChan->intMask;
/* enable this SCC's interrupt */
* M8260_SIMR_L(immrVal) |= pSccChan->intMask;
/* reset the receiver status bit */
* pSCCE = M8260_SCC_UART_SCCX_RX;
/* enable receive and transmit interrupts at the scc */
* pSCCM |= (M8260_SCC_UART_SCCX_RX | M8260_SCC_UART_SCCX_TX);
CACHE_PIPE_FLUSH ();
}
else
{
/* disable transmit and receive interrupts */
* pSCCM &= ~(M8260_SCC_UART_SCCX_RX | M8260_SCC_UART_SCCX_TX);
CACHE_PIPE_FLUSH ();
/* mask off this SCC's interrupt */
* M8260_SIMR_L(immrVal) &= (~(pSccChan->intMask));
}
pSccChan->channelMode = arg;
intUnlock(oldlevel);
break;
case SIO_MODE_GET:
* (int *) arg = pSccChan->channelMode;
break;
case SIO_AVAIL_MODES_GET:
*(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
break;
case SIO_HW_OPTS_SET:
/* wait for completion of previous transmit */
do
{
M8260_SCC_16_RD((pSccChan->pBdBase +
M8260_SCC_TX_BD_OFF +
M8260_SCC_BD_STAT_OFF), bdStatus);
} while (bdStatus & M8260_SCC_UART_TX_BD_READY);
if(arg & STOPB)
{
/* set stop bit to 2
* set PSMR[SL], can be changed on the fly
*/
* pPSMR |= M8260_SCC_UART_PSMR_SL;
}
else
{
/* set stop bit to 1
* clear PSMR[SL], it can be changed on the fly
*/
* pPSMR &= ~ M8260_SCC_UART_PSMR_SL;
}
break;
case SIO_HW_OPTS_GET:
default:
status = ENOSYS;
}
return (status);
}
/*******************************************************************************
*
* m8260SioInt - handle SCC interrupts
*
* This routine is called to handle SCC interrupts.
*
* RETURNS: NA
*/
void m8260SioInt
(
M8260_SCC_CHAN *pSccChan
)
{
char outChar;
VINT16 bdStatus; /* holder for the BD status */
UINT8 sccNum = pSccChan->sccNum; /* holder for the fcc number */
UINT8 scc = sccNum - 1; /* a convenience */
UINT32 immrVal = pSccChan->immrVal; /* holder for the immr value */
VINT16 *pSCCE = (VINT16 *) (immrVal + M8260_SCC_BASE + M8260_SCCE_OFFSET +
(scc * M8260_SCC_OFFSET_NEXT_SCC));
#ifdef DEBUG_SCC
static UINT32 numIsrEntriesTotal =0;
static UINT32 numIsrEntriesRx = 0;
static UINT32 numIsrEntriesTx = 0;
#endif
CACHE_PIPE_FLUSH ();
SCC_ISR_TOTAL_ADD;
SCC_LOG(1, "m8260SioInt: Total(%d). SCC%d.\n", numIsrEntriesTotal, pSccChan->sccNum, 3,4,5,6);
/* check for a Rx event */
if (* pSCCE & M8260_SCC_UART_SCCX_RX )
{
SCC_ISR_RX_ADD;
SCC_LOG(1, "m8260SioInt: Rx(%d). SCC%d.\n", numIsrEntriesRx, pSccChan->sccNum, 3,4,5,6);
/*
* clear receive event bit by setting the bit in the event register.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -