📄 st16c554sio.c
字号:
mask = ((*pChan->inByte) (pChan->msr)) & ST16C554_MSR_CTS; /* if the CTS is asserted enable Tx interrupt */ if (mask & ST16C554_MSR_CTS) ier |= ST16C554_IER_TBE; else ier &= (~ST16C554_IER_TBE); } else ier &= ~ST16C554_IER_MSI; /* disable modem status interrupt */ oldlevel = intLock (); (*pChan->outByte) (pChan->lcr, lcr); (*pChan->outByte) (pChan->mdc, mcr); /* now clear the port */ (*pChan->inByte) (pChan->data); if (options & CREAD) ier |= ST16C554_IER_RXRDY; if (pChan->channelMode == SIO_MODE_INT) { (*pChan->outByte) (pChan->ier, ier); } intUnlock (oldlevel); pChan->options = options; return OK; }/********************************************************************************* ST16C554Ioctl - special device control** Includes commands to get/set baud rate, mode(INT, POLL), hardware options(* parity, number of data bits), and modem control(RTS/CTS and DTR/DSR).* The ioctl commands SIO_HUP and SIO_OPEN are implemented to provide the * HUPCL( hang up on last close) function.** RETURNS: OK on success, EIO on device error, ENOSYS on unsupported* request.*/static int ST16C554Ioctl ( ST16C554_CHAN * pChan, /* device to control */ int request, /* request code */ int arg /* some argument */ ) { int test_ier; int ix; int baudH; int baudL; int oldlevel; UINT8 lcr; int status = OK; switch (request) { case SIO_BAUD_SET: status = (ST16C554BaudSet(pChan, arg) == OK) ? OK : EIO; break; case SIO_BAUD_GET: oldlevel = intLock(); status = EIO; lcr = (*pChan->inByte) (pChan->lcr); (*pChan->outByte) (pChan->lcr, (char)( lcr)); baudH = (*pChan->inByte)(pChan->brdh); baudL = (*pChan->inByte)(pChan->brdl); (*pChan->outByte) (pChan->lcr, lcr); for (ix = 0; ix < NELEMENTS (baudTable); ix++) { if ( baudH == MSB (baudTable[ix].preset) && baudL == LSB (baudTable[ix].preset) ) { *(int *)arg = baudTable[ix].rate; status = OK; } } intUnlock(oldlevel); break; case SIO_MODE_SET: status = (ST16C554ModeSet (pChan, arg) == OK) ? OK : EIO; break; case SIO_MODE_GET: *(int *)arg = pChan->channelMode; return (OK); case SIO_AVAIL_MODES_GET: *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL; return (OK); case SIO_HW_OPTS_SET: status = (ST16C554OptsSet (pChan, arg) == OK) ? OK : EIO; break; case SIO_HW_OPTS_GET: *(int *)arg = pChan->options; break; case SIO_HUP: /* check if hupcl option is enabled */ if (pChan->options & HUPCL) status = ST16C554Hup (pChan); break; case SIO_OPEN: /* check if hupcl option is enabled */ if (pChan->options & HUPCL) status = ST16C554Open (pChan); break; case SIO_INIT_IER: (*pChan->outByte) (pChan->ier, ST16C554_IER_RXRDY); test_ier = (*pChan->inByte)(pChan->ier); printf("\nier=%d",test_ier); (*pChan->outByte) (pChan->fcr, 0x00); test_ier = (*pChan->inByte)(pChan->fcr); printf("\nfcr=%d",test_ier); test_ier = (*pChan->inByte)(pChan->mdc); printf("\nMCR=%d",test_ier); test_ier = (*pChan->inByte)(pChan->msr); printf("\nmsr=%d",test_ier); test_ier = (*pChan->inByte)(pChan->lst); printf("\nlst=%d",test_ier); test_ier = (*pChan->inByte)(pChan->data); printf("\ndata=%d",test_ier); break; default: status = ENOSYS; break; } return (status); }/********************************************************************************* ST16C554Int - handle a receiver/transmitter interrupt** This routine handles four sources of interrupts from the UART. If there is* another character to be transmitted, the character is sent. When a modem* status interrupt occurs, the transmit interrupt is enabled if the CTS signal* is TRUE.** INTERNAL* The UART interrupts are prioritized in the following order by the Interrupt* Identification Register:** Bit 2 bit 1 bit 0 Priority Interrupt ID* -------------------------------------------------------* 0 0 1 none none* 1 1 0 0 serialization error or BREAK* 1 0 0 1 received data* 0 1 0 2 transmitter buffer empty* 0 0 0 3 RS-232 input**** In the table, priority level 0 is the highest priority. These priorities* are not typically configurable via software. The interrupt is expressed as* a two-bit integer. Bit 0, the pending bit, is negative logic - a value 0* means that an interrupt is pending.** When nested interrupts occur, the second interrupt is identified in the* Interrupt Identification Register (IIR) as soon as the first interrupt is* cleared. Therefore, the interrupt service routine must continue to read IIR* until bit-0 is 1.** When the 8250 generates an interrupt, all interrupts with an equal or* lower priority are locked out until the current interrupt has been cleared.* The operation required to clear an interrupt varies according to the source.* The actions typically required to clear an interrupt are as follows:** Source of interrupt Response required to reset* ---------------------------------------------------------------------* receiver error or BREAK read serialization status register* received data read data from receiver register* transmit buffer empty write to the transmitter or read* the interrupt ID register* RS-232 input read the RS-232 status register** In response to an empty transmit buffer (TBE), the interrupt can be* cleared by writing a byte to the transmitter buffer register. It can* also be cleared by reading the interrupt identification register.** Failure to clear all interrupts before returning will leave an interrupt* pending and prevent the UART from generating further interrupt requests* to the CPU.** RETURNS: N/A*/void ST16C554Int ( ST16C554_CHAN * pChan ) { char outChar; /* store a byte for transmission */ char interruptID; /* store contents of interrupt ID register */ char lineStatus; /* store contents of line status register */ char ier; /* store contents of interrupt enable register */ char rec_data; int ix = 0; /* allows us to return just in case IP never clears */ ier = (*pChan->inByte) (pChan->ier); /* service UART interrupts until IP bit set or read counter expires */ FOREVER { interruptID = ((*pChan->inByte)(pChan->iid) & ST16C554_IIR_MASK); /*printf("\nafter int id=%d",interruptID); printf("\nafter int ix=%d",ix);*/ if ((interruptID == ST16C554_IIR_IP) || (++ix > ST16C554_IIR_READ_MAX)) { break; /* interrupt cleared or loop counter expired */ } /* filter possible anomalous interrupt ID from PC87307VUL (SPR 26117) */ interruptID &= 0x0e; /* clear odd-bit to find interrupt ID */ if (interruptID == ST16C554_IIR_SEOB) { lineStatus = (*pChan->inByte) (pChan->lst); } else if (interruptID == ST16C554_IIR_RBRF) { if (pChan->putRcvChar != NULL) { (*pChan->putRcvChar)(pChan->putRcvArg, (*pChan->inByte) (pChan->data)); } else { (*pChan->inByte) (pChan->data); } /*printf("\nafter int id=%d",interruptID);*/ } else if (interruptID == ST16C554_IIR_THRE) { if ((pChan->getTxChar != NULL) && (*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK ) { (*pChan->outByte) (pChan->data, outChar); } /* There are no bytes available for transmission. Reading * the IIR at the top of this loop will clear the interrupt. */ } else if (interruptID == ST16C554_IIR_MSTAT) /* modem status register */ { char msr = (*(pChan)->inByte) (pChan->msr); printf("\ninterrupt msr!"); /* (|=) ... DON'T CLOBBER BITS ALREADY SET IN THE IER */ ier |= (ST16C554_IER_RXRDY | ST16C554_IER_MSI); /* if CTS is asserted by modem, enable tx interrupt */ if ((msr & ST16C554_MSR_CTS) && (msr & ST16C554_MSR_DCTS)) { (*pChan->outByte) (pChan->ier, (ST16C554_IER_TBE | ier)); } else /* turn off TBE interrupt until CTS from modem */ { (*pChan->outByte) (pChan->ier, (ier & (~ST16C554_IER_TBE))); } } /* else if(interruptID == ST16C554_IIR_TOUT) receive data time out { } */ } /* FOREVER */ }/********************************************************************************* ST16C554Startup - 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: OK*/LOCAL int ST16C554Startup ( ST16C554_CHAN * pChan /* tty device to start up */ ) { char ier = ST16C554_IER_RXRDY; char mask; if (pChan->channelMode == SIO_MODE_INT) { if (pChan->options & CLOCAL) { /* No modem control */ ier |= ST16C554_IER_TBE; } else { mask = ((*pChan->inByte) (pChan->msr)) & ST16C554_MSR_CTS; /* if the CTS is asserted enable Tx interrupt */ if (mask & ST16C554_MSR_CTS) ier |= (ST16C554_IER_TBE | ST16C554_IER_MSI); else ier |= (ST16C554_IER_MSI); } (*pChan->outByte) (pChan->ier, ier); } return (OK); }/******************************************************************************** ST16C554PRxChar - poll the device for input.** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the input buffer if empty.*/LOCAL int ST16C554PRxChar ( ST16C554_CHAN * pChan, /* pointer to channel */ char * pChar /* pointer to char */ ) { char pollStatus; pollStatus = ( *(pChan)->inByte) (pChan->lst); if ((pollStatus & ST16C554_LSR_RXRDY) == 0x00) return (EAGAIN); /* got a character */ *pChar = ( *(pChan)->inByte) (pChan->data); printf("\npoll the device for input!"); return (OK); }/******************************************************************************** ST16C554PTxChar - output a character in polled mode.* * Checks if the transmitter is empty. If empty, a character is written to* the data register. ** If the hardware flow control is enabled the handshake signal CTS has to be* asserted in order to send a character.** RETURNS: OK if a character arrived, EIO on device error, EAGAIN* if the output buffer if full.*/LOCAL int ST16C554PTxChar ( ST16C554_CHAN * pChan, /* pointer to channel */ char outChar /* char to send */ ) { char pollStatus; char msr; pollStatus = ( *(pChan)->inByte) (pChan->lst); msr = (*(pChan)->inByte) (pChan->msr); /* is the transmitter ready to accept a character? */ if ((pollStatus & ST16C554_LSR_TEMT) == 0x00) return (EAGAIN); if (!(pChan->options & CLOCAL)) /* modem flow control ? */ { if (msr & ST16C554_MSR_CTS) (*(pChan)->outByte) ((pChan)->data, outChar); else return (EAGAIN); } else (*(pChan)->outByte) ((pChan)->data, outChar); return (OK); }/*rec_data = (*pChan->inByte) (pChan->fcr); printf("\nfcr = %d", rec_data); rec_data = (*pChan->inByte) (pChan->lst); printf("\nlst = %d", rec_data); rec_data = (*pChan->inByte) (pChan->data); printf("\nreceive data: %c", rec_data); printf("\nreceive data: %d\n\n", rec_data);*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -