📄 m68302sio.c
字号:
{ while ((dataLen <= 0x80) && ((*pChan->getTxChar)(pChan->getTxArg, &outChar) == OK)) { pChan->pScc->txBd[0].dataPointer[dataLen++] = outChar; } if (dataLen > 0) { pChan->pScc->txBd[0].dataLength = dataLen; pChan->pScc->txBd[0].statusMode |= UART_TX_BD_READY; } } return (OK); }/**************************************************************************** m68302SioCallbackInstall - 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 m68302SioCallbackInstall ( SIO_CHAN *pSioChan, /* channel */ int callbackType, /* type of callback */ FUNCPTR callback, /* callback */ void *callbackArg /* parameter to callback */ ) { M68302_CHAN *pChan = (M68302_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); } }/*************************************************************************** m68302SioPollOutput - output a character in polled mode** Send out a single character in polled mode, if the transmitter is not* busy. If it is busy, then EAGAIN is returned and the caller routine* must try again later.** RETURNS:* Returns OK if a character arrived, EIO on device error, EAGAIN* if the output buffer if full. ENOSYS if the device is* interrupt-only.*/LOCAL int m68302SioPollOutput ( SIO_CHAN *pSioChan, char outChar ) { M68302_CHAN *pChan = (M68302_CHAN *)pSioChan; if (pChan->pScc->txBd[0].statusMode & UART_TX_BD_READY) return EAGAIN; /* reset the transmitter status bit */ pChan->pSccReg->scce = UART_SCCE_TX; /* fill buffer with data */ pChan->pScc->txBd[0].dataPointer[0] = outChar; pChan->pScc->txBd[0].dataLength = 1; pChan->pScc->txBd[0].statusMode |= UART_TX_BD_READY; return OK; }/******************************************************************************** m68302SioPollInput - poll the device for input** RETURNS:* Returns OK if a character arrived, EIO on device error, EAGAIN* if the input buffer if empty, ENOSYS if the device is* interrupt-only.*/LOCAL int m68302SioPollInput ( SIO_CHAN *pSioChan, char * thisChar ) { M68302_CHAN *pChan = (M68302_CHAN *)pSioChan; int nextBd; nextBd = pChan->rxBdNext; if (pChan->pScc->rxBd[nextBd].statusMode & UART_RX_BD_EMPTY) return EAGAIN; *thisChar = pChan->pScc->rxBd[nextBd].dataPointer[0]; pChan->pScc->rxBd[nextBd].statusMode |= UART_RX_BD_EMPTY; pChan->rxBdNext = (nextBd + 1) % RX_BD_NUM; /* reset RX event if no more data */ if (pChan->pScc->rxBd[pChan->rxBdNext].statusMode & UART_RX_BD_EMPTY) pChan->pSccReg->scce = UART_SCCE_RX; return OK; }/******************************************************************************** m68302ModeSet - toggle between interrupt and polled mode** Changes the mode of the channel. Note that only one channel can be* in polled mode at a time. Most drivers do not enforce this though.** RETURNS:* Returns OK on success, EIO on unsupported mode.*/LOCAL int m68302ModeSet ( M68302_CHAN *pChan, /* channel */ uint_t newMode /* new mode */ ) { int level; if (pChan == NULL || pChan->pScc == NULL || (newMode != SIO_MODE_POLL && newMode != SIO_MODE_INT)) return (EIO); if ((pChan->mode == SIO_MODE_POLL) && (newMode == SIO_MODE_INT)) { while (pChan->pScc->txBd[0].statusMode & UART_TX_BD_READY) ; } level = intLock (); if (newMode == SIO_MODE_INT && pChan->pCp->intEnable == TRUE) { /* interrupt mode */ *pChan->pCp->pIsr = pChan->intAck; /* reset ISR */ *pChan->pCp->pImr |= pChan->intAck; /* enable int */ pChan->pSccReg->scce = UART_SCCE_RX; /* reset rcv flag */ pChan->pSccReg->sccm = UART_SCCE_RX | UART_SCCE_TX; /* enable events */ } else if (newMode == SIO_MODE_POLL) { /* Polled mode */ pChan->pSccReg->sccm = 0; /* mask events */ *pChan->pCp->pImr &= ~(pChan->intAck); /* mask interrupts */ } pChan->mode = newMode; intUnlock (level); return (OK); }/******************************************************************************** m68302BaudSet - set baud rate for channel** Change the baud rate for the specified channel. The new baud rate* divisor is calculated and written to the scon register.** For very slow baud rates the divide by 4 bit will be turned on.* Otherwise it will be off.** NOTE: This driver can accept any baud rate as a valid value as long as* a valid divisor value can be computed. The exact range of valid baud* rates will depend on the system clock rate, but rates from 200 to 300,000* will usually be okay.** RETURNS:* Returns OK on success, EIO on unsupported mode.*/LOCAL int m68302BaudSet ( M68302_CHAN *pChan, int baud ) { int tempDiv; int baudClk; int divBy4=0; int scon; int oldLevel; /* Async clock is 1/16 the system clock, Sync clk = system clock */ baudClk = pChan->pCp->clockRate / 16; tempDiv = baudClk / baud; /* for slow baud rates, set divBy4 bit and recalc divisor */ if (tempDiv > (MAX_BRG_DIV + 1)) { tempDiv = (baudClk / 4) / baud; divBy4 = 1; } /* always subtract 1 */ tempDiv -= 1; /* check for valid divisor, return error indication if not valid */ if (tempDiv < MIN_BRG_DIV || tempDiv > MAX_BRG_DIV) return EIO; /* change current rate */ oldLevel = intLock (); scon = pChan->pSccReg->scon & 0xf000; scon |= (((tempDiv << 1) | divBy4) & 0x0fff); pChan->pSccReg->scon = scon; intUnlock (oldLevel); pChan->baud = baud; return OK; }/********************************************************************************* m68302SioIoctl - special device control** Perform device specific i/o control functions. This routine is called* from ttyDrv first, and if this routine returns ENOSYS, then ttyDrv will* call tyLib with the same arguments. The tyLib ioctl is not called if* this routine returns OK, or EIO.** RETURNS:* Returns OK on success, ENOSYS on unsupported request, EIO on failed* request.*/LOCAL int m68302SioIoctl ( SIO_CHAN *pSioChan, /* device to control */ int request, /* request code */ void * someArg /* some argument */ ) { M68302_CHAN *pChan = (M68302_CHAN *)pSioChan; int arg = (int)someArg; switch (request) { case SIO_BAUD_SET: /* set the baud rate */ return m68302BaudSet (pChan, arg); case SIO_BAUD_GET: /* Get the baud rate and return OK */ *(int *)arg = pChan->baud; return OK; case SIO_MODE_SET: /* * Set the mode (e.g., to interrupt or polled). Return OK * or EIO for an unknown or unsupported mode. */ return m68302ModeSet (pChan, arg); case SIO_MODE_GET: /* * Get the current mode and return OK. */ *(int *)arg = pChan->mode; return OK; case SIO_AVAIL_MODES_GET: /* * Get the available modes and return OK. */ *(int *)arg = (SIO_MODE_INT | SIO_MODE_POLL); return OK; case SIO_HW_OPTS_GET: /* * Optional command to get the hardware options (as defined * in sioLib.h). * Return OK or ENOSYS if this command is not implemented. * Note: if this command is unimplemented, it will be * assumed that the driver options are CREAD | CS8 (e.g., * eight data bits, one stop bit, no parity, ints enabled). */ *(int *)arg = pChan->options; return OK; case SIO_HW_OPTS_SET: /* * Optional command to set the hardware options (as defined * in sioLib.h). * Return OK, or ENOSYS if this command is not implemented. * Note: several hardware options are specified at once. * This routine should set as many as it can and then return * OK. The SIO_HW_OPTS_GET is used to find out which options * were actually set. */ return ENOSYS; default: return ENOSYS; } }/********************************************************************************* dummyCallback - dummy callback routine** RETURNS:* Always returs ERROR.** NOMANUAL*/LOCAL STATUS dummyCallback (void) { return ERROR; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -