📄 ixdp2400sio.c
字号:
{ FAST int oldlevel; /* current interrupt level mask */#if defined(NO_MODEM_CNTRL)#else char mask;#endif if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT)) return (ERROR); oldlevel = intLock (); if (newMode == SIO_MODE_INT) { /* Enable appropriate interrupts */ if (pChan->options & CLOCAL) { pChan->ier = pChan->ier | RxFIFO_BIT | TxFIFO_BIT | Rx_RLS |Rx_TIMEOUT; REG(IER, pChan) = pChan->ier; }#if defined(NO_MODEM_CNTRL)#else else { mask = REG(MSR, pChan) & MSR_CTS; /* if the CTS is asserted enable Tx interrupt */ if (mask & MSR_CTS) pChan->ier |= TxFIFO_BIT; /* enable Tx interrupt */ else pChan->ier &= (~TxFIFO_BIT); /* disable Tx interrupt */ REG(IER, pChan) = pChan->ier; } #endif } else { /* disable all UART interrupts */ REG(IER, pChan) = 0x40; } pChan->channelMode = newMode; intUnlock (oldlevel); return (OK); }/********************************************************************************* ixp2400Ioctl - special device control** Includes commands to get/set baud rate, mode(INT,POLL) and hardware options(* parity, number of data bits).* * RETURNS: OK on success, EIO on device error, ENOSYS on unsupported* request.*/LOCAL STATUS ixp2400Ioctl ( IXP2400_CHAN * pChan, /* pointer to channel */ int request, /* request code */ int arg /* some argument */ ) { FAST STATUS status; status = OK; switch (request) { case SIO_BAUD_SET: if (arg < IXP2400_MIN_RATE || arg > IXP2400_MAX_RATE) status = EIO; /* baud rate out of range */ else status = ixp2400BaudSet (pChan, arg); break; case SIO_BAUD_GET: *(int *)arg = pChan->baudRate; break; case SIO_MODE_SET: status = (ixp2400ModeSet (pChan, arg) == OK) ? OK : EIO; break; case SIO_MODE_GET: *(int *)arg = pChan->channelMode; break; case SIO_AVAIL_MODES_GET: *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL; break; case SIO_HW_OPTS_SET: status = (ixp2400OptsSet (pChan, arg) == OK) ? OK : EIO; break; case SIO_HW_OPTS_GET: *(int *)arg = pChan->options; break;#if defined(NO_MODEM_CNTRL)#else case SIO_HUP: /* check if hupcl option is enabled */ if (pChan->options & HUPCL) status = ixp2400Hup (pChan); break; case SIO_OPEN: /* check if hupcl option is enabled */ if (pChan->options & HUPCL) status = ixp2400Open (pChan); break;#endif default: status = ENOSYS; } return (status); }/********************************************************************************* ixp2400IntWr - handle a transmitter interrupt ** This routine handles write interrupts from the UART. It reads a character* and puts it in the transmit holding register of the device for transfer.** If there are no more characters to transmit, transmission is disabled by * clearing the transmit interrupt enable bit in the IER(int enable register).** RETURNS: N/A**/void ixp2400IntWr ( IXP2400_CHAN * pChan /* pointer to channel */ ) { char outChar; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) REG(THR,pChan) = outChar; /* write char to Transmit Holding Reg */ else { pChan->ier &= (~TxFIFO_BIT); /* indicates to disable Tx Int */ REG(IER, pChan) = pChan->ier; } }/********************************************************************************* ixp2400IntRd - handle a receiver interrupt ** This routine handles read interrupts from the UART.** RETURNS: N/A**/void ixp2400IntRd ( IXP2400_CHAN * pChan /* pointer to channel */ ) { char inchar; /* read character from Receive Holding Reg. */ inchar = REG(RBR, pChan); (*pChan->putRcvChar) (pChan->putRcvArg, inchar); }/********************************************************************************* ixp2400IntEx - miscellaneous interrupt processing** This routine handles miscellaneous interrupts on the UART.* Not implemented yet.** RETURNS: OK or ERROR**/STATUS ixp2400IntEx ( IXP2400_CHAN *pChan /* pointer to channel */ ) { /* Nothing for now... */ return OK; }/********************************************************************************** ixp2400Int - interrupt level processing** This routine handles three sources of interrupts from the UART. They are* prioritized in the following order by the Interrupt Identification Register:* Receiver Line Status, Received Data Ready and Transmit Holding Register Empty.** RETURNS: N/A**/void ixp2400Int ( IXP2400_CHAN * pChan /* pointer to channel */ ) { FAST volatile char intStatus; /* read the Interrrupt Status Register (Int. Ident.) */ intStatus = (REG(IIR, pChan)) & 0x0f; /* * This UART chip always produces level active interrupts, and the IIR * only indicates the highest priority interrupt. * In the case that receive and transmit interrupts happened at * the same time, we must clear both interrupt pending to prevent * edge-triggered interrupt(output from interrupt controller) from locking * up. One way doing it is to disable all the interrupts at the beginning * of the ISR and enable at the end. */ REG(IER,pChan) = 0x40; /* disable interrupt */ switch (intStatus) { case IIR_RLS: case IIR_TIMEOUT: /* overrun,parity error and break interrupt */ intStatus = REG(LSR, pChan); /* read LSR to reset interrupt */ break; case IIR_RDA: /* received data available */ /* * receiver FIFO interrupt. In some case, IIR_RDA will * not be indicated in IIR register when there is more * than one character in FIFO. */ ixp2400IntRd (pChan); /* RxChar Avail */ break; case IIR_THRE: /* transmitter holding register ready */ { char outChar; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) REG(THR, pChan) = outChar; /* char to Transmit Holding Reg */ else { pChan->ier &= (~TxFIFO_BIT); /* indicates to disable Tx Int */ } } break;#if defined(NO_MODEM_CNTRL)#else case IIR_MSTAT: /* modem status register */ { char msr; msr = REG(MSR, pChan); /* if CTS is asserted by modem, enable tx interrupt */ if ((msr & MSR_CTS) && (msr & MSR_DCTS)) pChan->ier |= TxFIFO_BIT; else pChan->ier &= (~TxFIFO_BIT); } break; #endif default: /* any other error */ intStatus = REG(LSR, pChan); /* read LSR to reset interrupt */ break; } REG(IER, pChan) = pChan->ier; /* enable interrupts accordingly */ }/********************************************************************************* ixp2400TxStartup - transmitter startup routine** Call interrupt level character output routine and enable interrupt if it is* in interrupt mode with no hardware flow control.* If the option for hardware flow control is enabled and CTS is set TRUE,* then the Tx interrupt is enabled.* * RETURNS: N/A*/LOCAL int ixp2400TxStartup ( IXP2400_CHAN * pChan /* pointer to channel */ ) {#if defined(NO_MODEM_CNTRL)#else char mask;#endif if (pChan->channelMode == SIO_MODE_INT) { if (pChan->options & CLOCAL) { int oldlevel = intLock (); pChan->ier |= TxFIFO_BIT; REG(IER,pChan) = pChan->ier; intUnlock (oldlevel); }#if defined(NO_MODEM_CNTRL)#else else { mask = REG(MSR, pChan) & MSR_CTS; /* if the CTS is asserted enable Tx interrupt */ if (mask & MSR_CTS) pChan->ier |= TxFIFO_BIT; /* enable Tx interrupt */ else pChan->ier &= (~TxFIFO_BIT); /* disable Tx interrupt */ REG(IER, pChan) = pChan->ier; }#endif return (OK); } else { return (ENOSYS); } }/******************************************************************************** ixp2400PollOutput - output a character in polled mode.** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the output buffer if full.*/LOCAL int ixp2400PollOutput ( IXP2400_CHAN * pChan, /* pointer to channel */ char outChar /* char to send */ ) { char pollStatus = REG(LSR, pChan);#if defined(NO_MODEM_CNTRL)#else char msr = REG(MSR, pChan);#endif /* is the transmitter ready to accept a character? */ if ((pollStatus & LSR_THRE) == 0x00) return (EAGAIN);#if defined(NO_MODEM_CNTRL)#else if (!(pChan->options & CLOCAL)) /* modem flow control ? */ { if (msr & MSR_CTS) REG(THR, pChan) = outChar; else return (EAGAIN); } else#endif REG(THR, pChan) = outChar; /* transmit character */ return (OK); }/******************************************************************************** ixp2400PollInput - poll the device for input.** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the input buffer if empty.*/LOCAL int ixp2400PollInput ( IXP2400_CHAN * pChan, /* pointer to channel */ char * pChar /* pointer to char */ ) { char pollStatus = REG(LSR, pChan); if ((pollStatus & LSR_DR) == 0x00) return (EAGAIN); /* got a character */ *pChar = REG(RBR, pChan); return (OK); }/******************************************************************************** ixp2400CallbackInstall - 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.*/LOCAL int ixp2400CallbackInstall ( SIO_CHAN * pSioChan, /* pointer to device to control */ int callbackType, /* callback type(tx or receive) */ STATUS (*callback)(), /* pointer to callback function */ void * callbackArg /* callback function argument */ ) { IXP2400_CHAN * pChan = (IXP2400_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 + -