📄 m68681sio.c
字号:
LOCAL int m68681TxStartup ( M68681_CHAN * pChan ) { char outChar; int lvl; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) { lvl = intLock (); M68681_WRITE (pChan->cr, M68681_CR_TX_ENABLE); M68681_WRITE (pChan->tb, outChar); intUnlock (lvl); } return (OK); }/******************************************************************************** m68681CallbackInstall - install ISR callbacks to get/put chars.** This driver allows interrupt callbacks, for transmitting characters* and receiving characters. In general, drivers may support other types* of callbacks too.** RETURNS:* Returns OK on success, or ENOSYS for an unsupported callback type.*/LOCAL int m68681CallbackInstall ( M68681_CHAN * pChan, int callbackType, STATUS (*callback)(), void * callbackArg ) { 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); } }/******************************************************************************** m68681PollOutput - output a character in polled mode.** This routine polls the status register to see if the TxRDY bit has been set.* This signals that the transmit holding register is empty and that the* specified DUART channel is ready for transmission.** RETURNS:* Returns OK if a character sent, EIO on device error, EAGAIN* if the output buffer is full.*/LOCAL int m68681PollOutput ( M68681_CHAN * pChan, char outChar ) { char statusReg; statusReg = M68681_READ (pChan->sr); /* is the transitter ready to accept a character? */ if ((statusReg & M68681_SR_TXRDY) == 0x00) return (EAGAIN); /* write out the character */ M68681_WRITE (pChan->tb, outChar); return (OK); }/******************************************************************************** m68681PollInput - poll the device for input.** This routine polls the status register to see if the RxRDY bit is set.* This gets set when the DUART receives a character and signals the* pressence of a character in the channels receive buffer.** RETURNS:* Returns OK if a character arrived, EIO on device error, EAGAIN* if the input buffer if empty.*/LOCAL int m68681PollInput ( M68681_CHAN * pChan, char * thisChar ) { char statusReg; statusReg = M68681_READ (pChan->sr); if ((statusReg & M68681_SR_RXRDY) == 0x00) return (EAGAIN); M68681_WRITE (thisChar, *pChan->rb); return (OK); }/******************************************************************************** m68681ModeSet - 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, transmitter interrupt and the* received break condition interrupt. If polled mode is desired the xmitrs for* the specified channel is enabled.** RETURNS:* Returns a status of OK if the mode was set else ERROR.*/LOCAL STATUS m68681ModeSet ( M68681_CHAN * pChan, UINT newMode ) { int oldlevel; if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT)) return (ERROR); oldlevel = intLock (); if (newMode == SIO_MODE_INT && pChan->pDuart->intEnable) { /* Enable the interrupts for receiver/transmitter conditions */ m68681ImrSetClr (pChan->pDuart, (pChan->rcvrEnb | pChan->xmitEnb), 0); } else { /* Disable interrupts and enable the transmitter for the channel */ m68681ImrSetClr (pChan->pDuart, 0, (pChan->rcvrEnb | pChan->xmitEnb)); M68681_WRITE (pChan->cr, M68681_CR_TX_ENABLE); } intUnlock (oldlevel); pChan->mode = newMode; return (OK); }/******************************************************************************** m68681BaudSet - change baud rate for channel** This routine sets the baud rate for the DUART. The interrupts are disabled* during chip access.** RETURNS:* Returns a status of OK if the baud rate was set else ERROR.*/LOCAL STATUS m68681BaudSet ( M68681_CHAN * pChan, UINT baud ) { int ix, oldlevel = intLock (); STATUS status = ERROR; for (ix = 0; ix < NELEMENTS (baudTable); ix ++) { if (baudTable [ix].rate == baud) { m68681AcrSetClr (pChan->pDuart, baudTable[ix].baudBit, M68681_ACR_BRG_SELECT); M68681_WRITE (pChan->csr, baudTable [ix].csrVal); pChan->baudRate = baud; status = OK; break; } } intUnlock (oldlevel); return (status); }/********************************************************************************* m68681InitStruct - initializes the channel structure** This routine initializes the specified channels driver functions.** RETURNS: N/A.*/LOCAL void m68681InitStruct ( M68681_CHAN * pChan ) { pChan->sio.pDrvFuncs= &m68681SioDrvFuncs; pChan->getTxChar = m68681DummyCallback; pChan->putRcvChar = m68681DummyCallback; pChan->mode = 0; /* undefined */ if (pChan->options == 0 || pChan->options > MAX_OPTIONS) pChan->options = M68681_DEFAULT_OPTIONS; if (pChan->baudRate == 0 || pChan->baudRate > MAX_BAUD) pChan->baudRate = M68681_DEFAULT_BAUD; }/********************************************************************************* m68681InitChannel - initialize a single channel** This routine initializes the specified channel. It is required* that the transmitters and receivers have been issued s/w reset commands* before the mode registers, clock select registers, auxillary clock* registers & output port configuration registers are changed.** This routine only sets the initial state as part of m68681DevInit. The* user can change this state through ioct clommands as desired.** RETURNS: N/A.*/LOCAL void m68681InitChannel ( M68681_CHAN * pChan, M68681_DUART * pDuart ) { /* Reset the transmitters & receivers */ M68681_WRITE (pChan->cr, M68681_CR_RST_BRK_INT_CMD); M68681_WRITE (pChan->cr, M68681_CR_RST_ERR_STS_CMD); m68681OptsSet (pChan, pChan->options); /* TX is disabled */ m68681BaudSet (pChan, pChan->baudRate); }/********************************************************************************* m68681OptsSet - set the serial options** Set the channel operating mode to that specified. All sioLib options* are supported: CLOCAL, CREAD, CSIZE, PARENB, and PARODD.** Note, this routine disables the transmitter. The calling routine* may have to re-enable it.** RETURNS:* Returns OK to indicate success, otherwise ERROR is returned*/LOCAL STATUS m68681OptsSet ( M68681_CHAN * pChan, /* ptr to channel */ UINT options /* new hardware options */ ) { int mr1Value = 0; int mr2Value = 0; int lvl; if (pChan == NULL || options & 0xffffff00) return ERROR; /* Reset the transmitters & receivers */ switch (options & CSIZE) { case CS5: mr1Value = M68681_MR1_BITS_CHAR_5; break; case CS6: mr1Value = M68681_MR1_BITS_CHAR_6; break; case CS7: mr1Value = M68681_MR1_BITS_CHAR_7; break; default: case CS8: mr1Value = M68681_MR1_BITS_CHAR_8; break; } if (options & STOPB) mr2Value = M68681_MR2_STOP_BITS_2; else mr2Value = M68681_MR2_STOP_BITS_1; switch (options & (PARENB|PARODD)) { case PARENB|PARODD: mr1Value |= M68681_MR1_ODD_PARITY; break; case PARENB: mr1Value |= M68681_MR1_EVEN_PARITY; break; case PARODD: mr1Value |= M68681_MR1_PAR_MODE_MULTI; break; default: case 0: mr1Value |= M68681_MR1_NO_PARITY; break; } if (!(options & CLOCAL)) { /* clocal disables hardware flow control */ mr1Value |= M68681_MR1_RX_RTS; mr2Value |= M68681_MR2_TX_CTS; } lvl = intLock (); /* now reset the channel mode registers */ M68681_WRITE (pChan->cr, M68681_CR_RST_MR_PTR_CMD | M68681_CR_RX_DISABLE | M68681_CR_TX_DISABLE); M68681_WRITE (pChan->cr, M68681_CR_RST_TX_CMD); M68681_WRITE (pChan->cr, M68681_CR_RST_RX_CMD); M68681_WRITE (pChan->mr, mr1Value); /* mode register 1 */ M68681_WRITE (pChan->mr, mr2Value); /* mode register 2 */ if (options & CREAD) M68681_WRITE (pChan->cr, M68681_CR_RX_ENABLE); intUnlock (lvl); pChan->options = options; return OK; }/********************************************************************************* m68681Ioctl - special device control** RETURNS:* Returns OK on success, EIO on device error, ENOSYS on unsupported* request.*/LOCAL int m68681Ioctl ( M68681_CHAN * pChan, /* device to control */ int request, /* request code */ void * someArg /* some argument */ ) { STATUS result; int arg = (int)someArg; switch (request) { case SIO_BAUD_SET: return (m68681BaudSet (pChan, arg) == OK ? OK : EIO); case SIO_BAUD_GET: *(int *)arg = pChan->baudRate; return (OK); case SIO_MODE_SET: return (m68681ModeSet (pChan, arg) == OK ? OK : EIO); case SIO_MODE_GET: *(int *)arg = pChan->mode; return (OK); case SIO_AVAIL_MODES_GET: *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL; return (OK); case SIO_HW_OPTS_SET: /* change options, then set mode to restart chip correctly */ result = m68681OptsSet (pChan, arg); m68681ModeSet (pChan, pChan->mode); return result; case SIO_HW_OPTS_GET: *(int *)arg = pChan->options; return (OK); default: return (ENOSYS); } }/********************************************************************************* m68681IntWr - handle a transmitter interrupt** This routine handles write interrupts from the DUART. This isr is invoked* when the TxRDY bit in the interrupt status register has been set. If there* is no character to transmit the transmitter for the channel is disabled.** RETURNS: N/A*/LOCAL void m68681IntWr ( M68681_CHAN * pChan ) { char outChar; volatile UCHAR *tb = pChan->tb; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) { M68681_WRITE (tb, outChar); /* if char available, tx it */ } else { M68681_WRITE (pChan->cr, M68681_CR_TX_DISABLE); } }/******************************************************************************* m68681IntRd - handle a reciever interrupt** This routine handles read interrupts from the DUART.* The DUART has been programmed to generate read interrupts when the RXRDY* status bit has been set in the interrupt status register. When a character* has been received it is removed from the channels receive buffer.** RETURNS: N/A*/LOCAL void m68681IntRd ( M68681_CHAN * pChan ) { volatile UCHAR *rb = pChan->rb; UCHAR inchar; char statusReg; statusReg = M68681_READ (pChan->sr); while ((statusReg & M68681_SR_RXRDY) != 0x00) { inchar = M68681_READ (rb); (*pChan->putRcvChar) (pChan->putRcvArg, inchar); if (pChan->mode != SIO_MODE_INT) break; statusReg = M68681_READ (pChan->sr); } }/********************************************************************************* m68681Int - handle all DUART interrupts in one vector** This routine handles all interrupts in a single interrupt vector.* It identifies and services each interrupting source in turn, using* edge-sensitive interrupt controllers.** RETURNS: N/A*/void m68681Int ( M68681_DUART * pDuart ) { UCHAR intStatus; volatile UCHAR resetTimer; /* loop until all sources have been handled */ while ((intStatus = (M68681_READ(pDuart->isr) & pDuart->imrCopy)) != 0) { if ((intStatus & M68681_ISR_TX_RDY_A_INT) != 0) m68681IntWr (&pDuart->portA); if ((intStatus & M68681_ISR_RX_RDY_A_INT) != 0) m68681IntRd (&pDuart->portA); if ((intStatus & M68681_ISR_TX_RDY_B_INT) != 0) m68681IntWr (&pDuart->portB); if ((intStatus & M68681_ISR_RX_RDY_B_INT) != 0) m68681IntRd (&pDuart->portB); if (intStatus & M68681_ISR_CTR_RDY_INT) { if (pDuart->tickRtn != NULL) (*pDuart->tickRtn) (pDuart->tickArg); else /* Clear the timer int */ resetTimer = M68681_READ (pDuart->ctroff); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -