📄 m8260sio.c
字号:
int arg /* some argument */ ) { int oldlevel; STATUS status = OK; int prescale; UINT8 sccNum = pSccChan->sccNum; /* holder for the fcc number */ UINT8 scc = sccNum - 1; /* a convenience */ UINT32 immrVal = pSccChan->immrVal; /* holder for the immr value */ VINT32 *pBRGC = (VINT32 *) (immrVal + M8260_BRGC_BASE + (scc * M8260_BRGC_OFFSET_NEXT_BRGC)); VINT16 *pSCCM = (VINT16 *) (immrVal + M8260_SCC_BASE + M8260_SCCM_OFFSET + (scc * M8260_SCC_OFFSET_NEXT_SCC)); switch (request) { case SIO_BAUD_SET: if (arg >= 300 && arg <= 38400) /* could go higher... */ {/* prescale = 625000 / arg; */ /* value for 40MHz */ /* for 66/133/133 system, it should be 1017600 not 625000 */ prescale = 1031250 / arg; /* value for 66MHz */ prescale++; /* add 1 as it counts to zero */ * pBRGC = 0x00010000 | (prescale << 1); 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 (arg == SIO_MODE_INT) { /* enable SCC interrupts at the SIU Interrupt Controller */ if (scc == 0) { m8260IntEnable(INUM_SCC1); }/* 8260pc : SCC 2 is not used */#if WITH_SCC2 else if (scc == 1) { m8260IntEnable(INUM_SCC2); }#endif /* 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 */ if (scc == 0) m8260IntDisable(INUM_SCC1);/* 8260pc : SCC 2 is not used */#if WITH_SCC2 else if (scc == 1) m8260IntDisable(INUM_SCC2);#endif CACHE_PIPE_FLUSH (); } 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; default: status = ENOSYS; } return (status); }/********************************************************************************* m8260SioInt - handle an SCC interrupt** 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)); CACHE_PIPE_FLUSH (); /* check for a receive event */ if (* pSCCE & M8260_SCC_UART_SCCX_RX ) { /* * clear receive event bit by setting the bit in the event register. * This also clears the bit in SIPNR */ * pSCCE = M8260_SCC_UART_SCCX_RX; CACHE_PIPE_FLUSH (); /* * as long as there is a character: * Inspect bit 0 of the status word which is the empty flag: * 0 if buffer is full or if there was an error * 1 if buffer is not full */ M8260_SCC_16_RD((pSccChan->pBdBase + M8260_SCC_RCV_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus); /* if bit is set there is nothing */ while (!(bdStatus & M8260_SCC_UART_RX_BD_EMPTY)) { M8260_SCC_8_RD(pSccChan->rcvBufferAddr, outChar); /* * indicate that we've processed this buffer; set empty * flag to 1 indicating that the buffer is empty */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_RCV_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus |= M8260_SCC_UART_RX_BD_EMPTY); /* necessary when switching from write to read */ CACHE_PIPE_FLUSH (); /* pass the received character up to the tty driver */ (*pSccChan->putRcvChar) (pSccChan->putRcvArg,outChar); /* if driver is in polled mode, we're done */ if (pSccChan->channelMode == SIO_MODE_POLL) break; /* * If interrupt mode, read the status again; * it's possible a new char has arrived */ M8260_SCC_16_RD((pSccChan->pBdBase + M8260_SCC_RCV_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus); } } /* check for a transmit event and if a character needs to be output */ /* transmit event */ CACHE_PIPE_FLUSH (); if ((* pSCCE & M8260_SCC_UART_SCCX_TX ) && (pSccChan->channelMode != SIO_MODE_POLL)) /* ...and we're not polling */ { /* * clear transmit event bit by setting the bit in the event register. * This also clears the bit in SIPNR */ * pSCCE = M8260_SCC_UART_SCCX_TX; CACHE_PIPE_FLUSH (); if ((*pSccChan->getTxChar) (pSccChan->getTxArg, &outChar) == OK) { CACHE_PIPE_FLUSH (); /* wait for the ready bit to be 0 meaning the buffer is free */ 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); M8260_SCC_8_WR(pSccChan->txBufferAddr, outChar); /* write char */ /* set buffer length */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_LEN_OFF), 0x0001); /* set ready bit so CPM will process buffer */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus |= M8260_SCC_UART_TX_BD_READY); CACHE_PIPE_FLUSH (); } } /* * acknowledge all other interrupts - ignore events. This also clears * the bit in SIPNR */ * pSCCE &= ~(M8260_SCC_UART_SCCX_TX | M8260_SCC_UART_SCCX_RX); CACHE_PIPE_FLUSH (); }/********************************************************************************* m8260SioStartup - transmitter startup routine* * Starts transmission on the indicated channel** RETURNS: NA*/LOCAL void m8260SioStartup ( M8260_SCC_CHAN *pSccChan /* ty device to start up */ ) { char outChar; UINT16 bdStatus; /* holder for the BD status */ if (pSccChan->channelMode == SIO_MODE_POLL) return; /* * check if a transmit buffer is ready and if a character needs to be * output */ CACHE_PIPE_FLUSH (); /* before first read */ M8260_SCC_16_RD((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus); if (!(bdStatus & M8260_SCC_UART_TX_BD_READY)) if ((*pSccChan->getTxChar) (pSccChan->getTxArg, &outChar) == OK) { /* write char; set length; flag buffer as not empty */ M8260_SCC_8_WR(pSccChan->txBufferAddr, outChar); /* write char */ /* set buffer length */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_LEN_OFF), 0x0001); /* flag buffer as not empty */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus |= 0x8000); } CACHE_PIPE_FLUSH (); }/******************************************************************************** m8260SioPollInput - poll the device for input.** Poll the indicated device for input characters** RETURNS: OK if a character arrived, ERROR on device error, EAGAIN* if the input buffer is empty.*/LOCAL int m8260SioPollInput ( SIO_CHAN * pSioChan, char * thisChar ) { M8260_SCC_CHAN * pSccChan = (M8260_SCC_CHAN *) pSioChan; UINT16 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)); CACHE_PIPE_FLUSH (); /* is there a receive event? */ if (!(* pSCCE & M8260_SCC_UART_SCCX_RX )) return (EAGAIN); /* is the buffer empty? */ M8260_SCC_16_RD((pSccChan->pBdBase + M8260_SCC_RCV_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus); /* if bit is high there is nothing */ if (bdStatus & M8260_SCC_UART_RX_BD_EMPTY) return (EAGAIN); /* get a character */ M8260_SCC_8_RD(pSccChan->rcvBufferAddr, * thisChar); /* set the empty bit */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_RCV_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus |= M8260_SCC_UART_RX_BD_EMPTY); CACHE_PIPE_FLUSH (); /* only clear RX event if no more characters are ready */ M8260_SCC_16_RD((pSccChan->pBdBase + M8260_SCC_RCV_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus); CACHE_PIPE_FLUSH (); /* if bit is high there is nothing */ if (bdStatus & M8260_SCC_UART_RX_BD_EMPTY) *pSCCE = M8260_SCC_UART_SCCX_RX; /* clear rx event bit */ CACHE_PIPE_FLUSH (); return (OK); }/******************************************************************************** m8260SioPollOutput - output a character in polled mode.** Transmit a character in polled mode** RETURNS: OK if a character is sent, ERROR on device error, EAGAIN* if the output buffer if full.*/static int m8260SioPollOutput ( SIO_CHAN * pSioChan, char outChar ) { M8260_SCC_CHAN * pSccChan = (M8260_SCC_CHAN *) pSioChan; int i; UINT16 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)); CACHE_PIPE_FLUSH (); /* * wait a bit for the last character to get out * because the PPC603 is a very fast processor */ for (i=0; i<M8260_SCC_POLL_OUT_DELAY; i++) ; /* * is the transmitter ready yet to accept a character? * if still not, we have a problem */ M8260_SCC_16_RD((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus); if (!(bdStatus & 0x8000)) return(EAGAIN); /* reset the transmitter status bit */ /* * clear transmit event bit by setting the bit in the event register. * This also clears the bit in SIPNR */ * pSCCE = M8260_SCC_UART_SCCX_TX; /* write char; set length; flag buffer as not empty */ M8260_SCC_8_WR(pSccChan->txBufferAddr, outChar); /* write char */ /* set buffer length */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_LEN_OFF), 0x0001); /* flag buffer as not empty */ M8260_SCC_16_WR((pSccChan->pBdBase + M8260_SCC_TX_BD_OFF + M8260_SCC_BD_STAT_OFF), bdStatus |= M8260_SCC_UART_TX_BD_READY); CACHE_PIPE_FLUSH (); return (OK); }/******************************************************************************** m8260SioCallbackInstall - install ISR callbacks to get and put chars.** Install the indicated ISR callback functions that are used to get and* put characters** RETURNS: NA**/static int m8260SioCallbackInstall ( SIO_CHAN * pSioChan, int callbackType, STATUS (* callback)(), void * callbackArg ) { M8260_SCC_CHAN * pSccChan = (M8260_SCC_CHAN *) pSioChan; CACHE_PIPE_FLUSH (); switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pSccChan->getTxChar = callback; pSccChan->getTxArg = callbackArg; return (OK); break; case SIO_CALLBACK_PUT_RCV_CHAR: pSccChan->putRcvChar = callback; pSccChan->putRcvArg = callbackArg; return (OK); break; default: return (ENOSYS); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -