📄 s3c2410xsio.c
字号:
int lvl;
switch (request)
{
case SIO_BAUD_SET:
if(arg < s3c2410x_BAUD_MIN || arg > s3c2410x_BAUD_MAX) return(EIO);
/* disable interrupts during chip access */
oldlevel = intLock ();
s3c2410x_UART_REG_WRITE(pChan,OFFSET_UDIV,(((s3c2410x_PCLK/16)/arg)-1));
intUnlock (oldlevel);
s3c2410x_UART_REG_READ(pChan,OFFSET_UDIV,tempUINT32);
pChan->baudRate=((s3c2410x_PCLK/16)/(tempUINT32+1));
break;
case SIO_BAUD_GET:
*(int *)arg = pChan->baudRate;
break;
case SIO_MODE_SET:
switch(arg)
{
case SIO_MODE_INT:
/* clear subpend-flag of RX_TX */
switch((int)(pChan->regs))
{
case UART_1_BASE_ADR:
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_SUBSRCPND,((1<<SUBINT_LVL_TXD1)|(1<<SUBINT_LVL_RXD1)));
break;
case UART_0_BASE_ADR:
default:
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_SUBSRCPND,((1<<SUBINT_LVL_TXD0)|(1<<SUBINT_LVL_RXD0)));
}
/* enable uart_int */
intEnable(pChan->intLevelRx);
/* enable subInterrupt for UART0. */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_INTSUBMSK,tempUINT32);
switch((int)(pChan->regs))
{
case UART_1_BASE_ADR:
tempUINT32 &= ~((1<<SUBINT_LVL_RXD1)|(1<<SUBINT_LVL_TXD1));
break;
case UART_0_BASE_ADR:
default:
tempUINT32 &= ~((1<<SUBINT_LVL_RXD0)|(1<<SUBINT_LVL_TXD0));
}
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTSUBMSK,tempUINT32);
break;
case SIO_MODE_POLL:
/* disable uart_int */
intDisable(pChan->intLevelRx);
/* disable subInterrupt for UART0. */
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_INTSUBMSK,tempUINT32);
switch((int)(pChan->regs))
{
case UART_1_BASE_ADR:
tempUINT32 |= ((1<<SUBINT_LVL_RXD1)|(1<<SUBINT_LVL_TXD1));
break;
case UART_0_BASE_ADR:
default:
tempUINT32 |= ((1<<SUBINT_LVL_RXD0)|(1<<SUBINT_LVL_TXD0));
}
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTSUBMSK,tempUINT32);
break;
default: return(EIO);
}
pChan->channelMode = arg;
break;
case SIO_MODE_GET:
*(int *)arg = pChan->channelMode;
break;
case SIO_AVAIL_MODES_GET:
/* Get the available modes and return OK. */
*(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
break;
case SIO_HW_OPTS_SET:
if(arg & 0xffffff00) return EIO;
/* do nothing if options already set */
if(pChan->options == arg) break;
switch (arg & CSIZE)
{
case CS5:
tempUINT32 = DATABIT_5; break;
case CS6:
tempUINT32 = DATABIT_6; break;
case CS7:
tempUINT32 = DATABIT_7; break;
default:
case CS8:
tempUINT32 = DATABIT_8; break;
}
if (arg & STOPB)
{
tempUINT32 |= TWO_STOPBIT;
}
else
{
/* tempUINT32 &= ~TWO_STOPBIT */;
}
switch (arg & (PARENB|PARODD))
{
case PARENB|PARODD:
tempUINT32 += ODD_PARITY;
break;
case PARENB:
tempUINT32 += EVEN_PARITY;
break;
case 0:
default:
;/* no parity */
}
lvl = intLock();
s3c2410x_UART_REG_WRITE(pChan,OFFSET_ULCON,tempUINT32);
intUnlock(lvl);
if (arg & CLOCAL)
{
/* clocal disables hardware flow control */
lvl = intLock();
s3c2410x_UART_REG_WRITE(pChan,OFFSET_UMCON,AFC_OFF);
intUnlock(lvl);
}
else
{
lvl = intLock();
s3c2410x_UART_REG_WRITE(pChan,OFFSET_UMCON,AFC_ON);
intUnlock(lvl);
}
pChan->options = arg;
break;
case SIO_HW_OPTS_GET:
*(int*)arg = pChan->options;
return (OK);
case SIO_HUP:
/* check if hupcl option is enabled */
break;
case SIO_OPEN:
break; /* always open */
default:
return (ENOSYS);
}
return (OK);
}
/*
* s3c2410xSioIntTx - handle a transmitter interrupt
*
* This routine handles write interrupts from the UART.
*
* RETURNS: N/A
*/
void s3c2410xSioIntTx
(
s3c2410x_CHAN * pChan /* ptr to s3c2410x_CHAN describing this channel */
)
{
char outChar;
/* clear subpending of the TXn */
switch((int)(pChan->regs))
{
case UART_1_BASE_ADR:
s3c2410x_IO_WRITE(s3c2410x_INT_CSR_SUBSRCPND, (1<<SUBINT_LVL_TXD1));
break;
case UART_0_BASE_ADR:
default:
s3c2410x_IO_WRITE(s3c2410x_INT_CSR_SUBSRCPND, (1<<SUBINT_LVL_TXD0));
}
if((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
{
/* write char. to Transmit Holding Reg. */
s3c2410x_UART_REG_WRITE(pChan, OFFSET_UTXH, (((UINT32)outChar)&0x000000ff));
}
}
/*
* s3c2410xSioIntRx - handle a receiver interrupt
*
* This routine handles read interrupts from the UART.
*
* RETURNS: N/A
*/
void s3c2410xSioIntRx
(
s3c2410x_CHAN * pChan /* ptr to s3c2410x_CHAN describing this channel */
)
{
char inchar;
/* clear subpending of the RXn */
switch((int)(pChan->regs))
{
case UART_1_BASE_ADR:
s3c2410x_IO_WRITE(s3c2410x_INT_CSR_SUBSRCPND, (1<<SUBINT_LVL_RXD1));
break;
case UART_0_BASE_ADR:
default:
s3c2410x_IO_WRITE(s3c2410x_INT_CSR_SUBSRCPND, (1<<SUBINT_LVL_RXD0));
}
/* read character from Receive Holding Reg. */
s3c2410x_UART_REG_READ(pChan, OFFSET_URXH, inchar);
(*pChan->putRcvChar) (pChan->putRcvArg, inchar);
}
/*
* s3c2410xSioInt - handle any UART interrupt
*
* This routine handles interrupts from the UART and determines whether
* the source is a transmit interrupt or receive/receive-timeout interrupt.
*
* The Prime Cell UART generates a receive interrupt when the RX FIFO is
* half-full, and a receive-timeout interrupt after 32 bit-clocks have
* elapsed with no incoming data.
*
* RETURNS: N/A
*/
void s3c2410xSioInt
(
s3c2410x_CHAN * pChan /* ptr to s3c2410x_CHAN describing this channel */
)
{
UINT32 intId;
s3c2410x_INT_REG_READ(s3c2410x_INT_CSR_SUBSRCPND, intId);
if(intId & ((1<<SUBINT_LVL_TXD0)|(1<<SUBINT_LVL_TXD1)))
{
s3c2410xSioIntTx(pChan);
}
if(intId & ((1<<SUBINT_LVL_RXD0)|(1<<SUBINT_LVL_RXD1)))
{
s3c2410xSioIntRx (pChan);
}
s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_INTSUBMSK, 0);
/* clear pend and enable this level */
/*s3c2410x_INT_REG_WRITE(s3c2410x_INT_CSR_SRCPND, (1<<(pChan->intLevelRx)));
s3c2410xIntLvlEnable(pChan->intLevelRx);
*/
}
/*
* s3c2410xTxStartup - transmitter startup routine
*
* Enable interrupt so that interrupt-level char output routine will be called.
*
* RETURNS: OK on success, ENOSYS if the device is polled-only, or
* EIO on hardware error.
*/
LOCAL int s3c2410xTxStartup
(
SIO_CHAN * pSioChan /* ptr to SIO_CHAN describing this channel */
)
{
s3c2410x_CHAN * pChan = (s3c2410x_CHAN *)pSioChan;
if(pChan->channelMode == SIO_MODE_INT)
{
intEnable(pChan->intLevelTx);
s3c2410xSioIntTx(pChan);
return OK;
}
else
{
return ENOSYS;
}
}
/*
* s3c2410xPollOutput - output a character in polled mode.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer is full, ENOSYS if the device is interrupt-only.
*/
LOCAL int s3c2410xPollOutput
(
SIO_CHAN* pSioChan, /* ptr to SIO_CHAN describing this channel */
char outChar /* to output */
)
{
s3c2410x_CHAN * pChan = (s3c2410x_CHAN *)pSioChan;
FAST UINT32 pollStatus;
s3c2410x_UART_REG_READ(pChan, OFFSET_UTRSTAT, pollStatus);
/* is the transmitter ready to accept a character? */
if(!(pollStatus & UTRSTAT_TRNSR_EM))
{
return EAGAIN;
}
/* write out the character */
s3c2410x_UART_REG_WRITE(pChan, OFFSET_UTXH, outChar); /* transmit character */
return OK;
}
/*
* s3c2410xPollInput - poll the device for input.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer is empty, ENOSYS if the device is interrupt-only.
*/
LOCAL int s3c2410xPollInput
(
SIO_CHAN * pSioChan, /* ptr to SIO_CHAN describing this channel */
char* thisChar /* pointer to where to return character */
)
{
s3c2410x_CHAN * pChan = (s3c2410x_CHAN *)pSioChan;
FAST UINT32 pollStatus;
s3c2410x_UART_REG_READ(pChan, OFFSET_UTRSTAT, pollStatus);
if(!(pollStatus & UTRSTAT_RB_RDY))
{
return EAGAIN;
}
/* got a character */
s3c2410x_UART_REG_READ(pChan, OFFSET_URXH, *thisChar);
return OK;
}
/*
* s3c2410xCallbackInstall - install ISR callbacks to get/put chars.
*
* This routine installs interrupt callbacks for transmitting characters
* and receiving characters.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
*
*/
LOCAL int s3c2410xCallbackInstall
(
SIO_CHAN* pSioChan, /* ptr to SIO_CHAN describing this channel */
int callbackType, /* type of callback */
STATUS (*callback)(), /* callback */
void* callbackArg /* parameter to callback */
)
{
s3c2410x_CHAN * pChan = (s3c2410x_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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -