www.pudn.com > vXworksBSPfors3c44b0.rar > sngks32cSio.c
/* sngks32cSio.c - Samsung S3C44B0X serial driver */ /* Copyright 1984-2001 Wind River Systems, Inc. */ #include "copyright_wrs.h" /* modification history -------------------- 01o,27jul04,a_m BSP定制 for 多刃剑开发板 01c,30nov01,m_h Save pChan->baudRate when setting baud 01b,26apr01,m_h convert tabs to spaces for readability 01a,12apr01,m_h created from snds100 template. */ /* DESCRIPTION This is the serial I/O driver for Samsung's KS32C50100 microprocessor which is an ARM based processor with several integrated peripherals. It has an interrupt controller, two 32-bit timers, one Ethernet controller,two HDLC controllers, one IIC controller, general purpose I/O ports, and a 2 channel DMA controller. The 2 UART channels integrated with the processor are controlled by this driver. Both the UARTs can work in interrupt mode as well as DMA mode. This driver supports only the interrupt mode for the UARTs. All the UART registers are accessible as 32-bit integers from the internal system registers. The macros SNGKS32C_REG_READ and SNGKS32C_REG_WRITE read and write 32-bit integers from and to the given addresses. SNGKS32C_SIO_DEFAULT_BAUD is defined to 38400 in this file. This is the default baud rate with which the UART channels will be initialized. The channels are also initialized with one start bit, one stop bit, 8 bit data and no parity bits. The driver is typically only called only by the BSP. The directly callable routines in this module are sngks32cDevInit(), sngks32cDevInit2(), sngks32cIntRcv(), sngks32cIntTx(), and sngks32cIntErr(). The BSP calls sngks32cDevInit() to initialize or reset the device. It connects the driver's interrupt handlers (sngks32cIntRcv(), sngks32cIntTx(), and sngks32cIntErr()), using intConnect(). After connecting the interrupt handlers, the BSP calls sngks32cDevInit2() to inform the driver that interrupt mode operation is now possible. INCLUDES: sngks32cSio.h sioLib.h SEE ALSO:*/ #include "vxWorks.h" #include "sioLib.h" #include "intLib.h" #include "errno.h" #include "sngks32cSio.h" #include "ioLib.h" #define SNGKS32C_BAUD_MIN 1200 #define SNGKS32C_BAUD_MAX 460860 #define SNGKS32C_SIO_DEFAULT_BAUD 38400 /* Hardware abstraction macros */ /* local defines */ #ifndef SNGKS32C_SIO_REG_READ #define SNGKS32C_SIO_REG_READ(pChan, reg, result) \ ((result) = (*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg)))) #endif /*SNGKS32C_SIO_REG_READ*/ #ifndef SNGKS32C_SIO_REG_WRITE #define SNGKS32C_SIO_REG_WRITE(pChan, reg, data) \ ((*(volatile UINT32 *)((UINT32)(pChan)->regs + (reg))) = (data)) #endif /*SNGKS32C_SIO_REG_WRITE*/ /* for backward compatibility */ #ifndef SIO_HUP # define SIO_OPEN 0x100A /* open channel, raise DTR, RTS */ # define SIO_HUP 0x100B /* hang-up, lower DTR, RTS */ #endif /* forward static declarations */ LOCAL int sngks32cTxStartup (SIO_CHAN * pSioChan); LOCAL int sngks32cCallbackInstall (SIO_CHAN *pSioChan, int callbackType, STATUS (*callback)(), void *callbackArg); LOCAL int sngks32cPollOutput (SIO_CHAN *pSioChan, char outChar); LOCAL int sngks32cPollInput (SIO_CHAN *pSioChan, char *thisChar); LOCAL int sngks32cIoctl (SIO_CHAN *pSioChan, int request, void *arg); LOCAL STATUS dummyCallback (void); /* local variables */ LOCAL SIO_DRV_FUNCS sngks32cSioDrvFuncs = { sngks32cIoctl, sngks32cTxStartup, sngks32cCallbackInstall, sngks32cPollInput, sngks32cPollOutput }; LOCAL BOOL sngks32cIntrMode = FALSE; /* interrupt mode allowed flag */ /****************************************************************************** * * sngks32cDevInit - initialize a SNGKS32C_DUSART * * This routine initializes the driver * function pointers and then resets the chip in a quiescent state. * The BSP must have already initialized all the device addresses and the * baudFreq fields in the SNGKS32C_DUSART structure before passing it to * this routine. * * RETURNS: N/A */ void sngks32cDevInit ( SNGKS32C_CHAN * pChan ) { /* initialize each channel's driver function pointers */ pChan->sio.pDrvFuncs = &sngks32cSioDrvFuncs; /* install dummy driver callbacks */ pChan->getTxChar = dummyCallback; pChan->putRcvChar = dummyCallback; /* reset the chip */ /*SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_ULCON,(INT_CLK | PARITY_NONE | ONE_STOP | WORD_LEN));*/ /* : deleeted and added */ SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_ULCON,(PARITY_NONE | ONE_STOP | WORD_LEN)); SNGKS32C_SIO_REG_WRITE(pChan,S3C44B0X_UFCON,0x97); /*0值禁止使用FIFO*/ SNGKS32C_SIO_REG_WRITE(pChan,S3C44B0X_UMCON,0); /* setting polled mode is one way to make the device quiet */ sngks32cIoctl ((SIO_CHAN *)pChan, SIO_MODE_SET, (void *)SIO_MODE_POLL); sngks32cIoctl ((SIO_CHAN *)pChan, SIO_BAUD_SET, (void *)SNGKS32C_SIO_DEFAULT_BAUD); } /****************************************************************************** * * sngks32cDevInit2 - initialize a SNGKS32C_DUSART, part 2 * * This routine is called by the BSP after interrupts have been connected. * The driver can now operate in interrupt mode. Before this routine is * called only polled mode operations should be allowed. * * RETURNS: N/A * ARGSUSED */ void sngks32cDevInit2 ( SNGKS32C_CHAN * pChan /* device to initialize */ ) { char outchar = '\0'; UINT32 status; /* * Dummy write to TXBUF to start TX empty interrupt */ SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UTXBUF,outchar); /* Interrupt mode is allowed */ /*SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_RX|UCON_TX|UCON_BREAK);*/ /* : deleted and added */ SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_TX_LEVEL|UCON_RX|UCON_TX|0x80); SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status); while ((status & USTAT_TX_READY) != USTAT_TX_READY) SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status); /* : added */ /*SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_RX|UCON_TX);*/ /* : deleted and added */ SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON,UCON_TX_LEVEL|UCON_RX|UCON_TX|0x80); sngks32cIntrMode = TRUE; } /****************************************************************************** * * sngks32cIntRcv - handle a channel's receive-character interrupt * * RETURNS: N/A */ void sngks32cIntRcv ( SNGKS32C_CHAN * pChan /* channel generating the interrupt */ ) { char inChar; UINT32 status; FAST int oldlevel; /* : added */ oldlevel = intLock (); /* : added */ /* * Grab the input character from the chip and hand it off via a * callback. For chips with input FIFO's it is more efficient * to empty the entire FIFO here. */ /*SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status); if((status & USTAT_RX_READY) == USTAT_RX_READY) { SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_URXBUF, inChar); (*pChan->putRcvChar) (pChan->putRcvArg, inChar); }*/ /* : deleted and added, 循环处理FIFO */ while(1){ SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status); if((status & UFSTAT_RX_COUNT) == 0) break; SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_URXBUF, inChar); (*pChan->putRcvChar) (pChan->putRcvArg, inChar); } intUnlock (oldlevel); /* : added */ } static int sending = 0; /* : added */ /****************************************************************************** * * sngks32cIntTx - handle a channels transmitter-ready interrupt * * RETURNS: N/A */ void sngks32cIntTx ( SNGKS32C_CHAN * pChan /* channel generating the interrupt */ ) { char outChar; UINT32 status; FAST int oldlevel; /* : added */ /* * If there's a character to transmit then write it out, else reset * the transmitter. For chips with output FIFO's it is more efficient * to fill the entire FIFO here. */ /*SNGKS32C_SIO_REG_READ(pChan,SNGKS32C_USTAT, status); if((status & USTAT_TX_READY) != USTAT_TX_READY) return;*/ /* : deleted and added, 针对FIFO */ SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status); if((status & UFSTAT_TX_FULL) == UFSTAT_TX_FULL) return; oldlevel = intLock (); /* : added */ if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR){ SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); while(1){ /* : added */ SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status); if((status & UFSTAT_TX_FULL) == UFSTAT_TX_FULL) break; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) == ERROR) break; SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); } } else { intDisable (pChan->intLevelTx); sending = 0; /* : added */ /**(UINT32 *) S3C44B0X_INTPEND = (1 << pChan->intLevelTx);*/ /* : deleted and added */ *(UINT32 *) S3C44B0X_I_ISPC = (1 << pChan->intLevelTx); } intUnlock (oldlevel); } /****************************************************************************** * * sngks32cTxStartup - start the interrupt transmitter * * RETURNS: OK on success, ENOSYS if the device is polled-only, or * EIO on hardware error. */ LOCAL int sngks32cTxStartup ( SIO_CHAN * pSioChan /* channel to start */ ) { char outChar; /* : added */ UINT32 status; /* : added */ FAST int oldlevel; /* : added */ SNGKS32C_CHAN * pChan = (SNGKS32C_CHAN *)pSioChan; /* : deleted */ /**(UINT32 *) SNGKS32C_INTPENDTST |= (1 << pChan->intLevelTx);*/ /* : added */ SNGKS32C_SIO_REG_READ(pChan,S3C44B0X_UFSTAT, status); if((status & UFSTAT_TX_FULL) == UFSTAT_TX_FULL) return (OK); if(sending == 1) return OK; oldlevel = intLock (); intEnable (pChan->intLevelTx); /* : added */ sending = 1; if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); intUnlock (oldlevel); return (OK); } /****************************************************************************** * * sngks32cCallbackInstall - 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: OK on success, or ENOSYS for an unsupported callback type. */ LOCAL int sngks32cCallbackInstall ( SIO_CHAN * pSioChan, /* channel */ int callbackType, /* type of callback */ STATUS (*callback)(), /* callback */ void * callbackArg /* parameter to callback */ ) { SNGKS32C_CHAN * pChan = (SNGKS32C_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); } } /******************************************************************************* * * sngks32cPollOutput - output a character in polled mode * * 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 sngks32cPollOutput ( SIO_CHAN *pSioChan, char outChar ) { SNGKS32C_CHAN * pChan = (SNGKS32C_CHAN *)pSioChan; UINT32 status; /* is the transmitter ready to accept a character? */ SNGKS32C_SIO_REG_READ (pChan, SNGKS32C_USTAT, status); if ((status & USTAT_TX_READY) == 0x00) return (EAGAIN); /* write out the character */ SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_UTXBUF, outChar); return (OK); } /****************************************************************************** * * sngks32cPollInput - poll the device for input * * 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 sngks32cPollInput ( SIO_CHAN * pSioChan, char * thisChar ) { SNGKS32C_CHAN * pChan = (SNGKS32C_CHAN *)pSioChan; UINT32 status; SNGKS32C_SIO_REG_READ (pChan,SNGKS32C_USTAT, status); if ((status & USTAT_RX_AVAIL) == 0x00) return (EAGAIN); /* no input available at this time */ /* got a character */ SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_URXBUF, *thisChar); return (OK); } /****************************************************************************** * * sngks32cModeSet - toggle between interrupt and polled mode * * RETURNS: OK on success, EIO on unsupported mode. */ LOCAL int sngks32cModeSet ( SNGKS32C_CHAN * pChan, /* channel */ uint_t newMode /* new mode */ ) { UINT32 temp; if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT)) return (EIO); /* Don't enter interrupt mode unless it is allowed. */ if ((newMode == SIO_MODE_INT) && (!sngks32cIntrMode)) return (EIO); /* set the new mode */ pChan->mode = newMode; if (pChan->mode == SIO_MODE_INT) { SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_UCON, temp); temp &=UCON_RX_TX_RESET; /**Reset RX and TX mode bits*/ temp |= (UCON_RX|UCON_TX); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON, temp); intEnable(pChan->intLevelRx); } else { SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_UCON, temp); temp &=UCON_RX_TX_RESET; /**Reset RX and TX mode bits*/ temp |= (UCON_RX|UCON_TX); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UCON, temp); intDisable (pChan->intLevelTx); intDisable (pChan->intLevelRx); } return (OK); } /******************************************************************************* * * sngks32cHup - hang up the modem control lines * * Resets the RTS and DTR signals. * * RETURNS: OK */ LOCAL STATUS sngks32cHup ( SNGKS32C_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ oldlevel = intLock (); /* set RTS and DTR low */ /* SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_USTAT, USTAT_DTR_LOW); */ intUnlock (oldlevel); return (OK); } /******************************************************************************* * * sngks32cOpen - Set the modem control lines * * Set the modem control lines(RTS, DTR) TRUE if not already set. * * RETURNS: OK */ LOCAL STATUS sngks32cOpen ( SNGKS32C_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ oldlevel = intLock (); /* set RTS and DTR active */ /* SNGKS32C_SIO_REG_WRITE(pChan, SNGKS32C_USTAT, USTAT_DTR_HIGH); */ intUnlock (oldlevel); return (OK); } /****************************************************************************** * * sngks32cOptSet - set hardware options * * This routine sets up the hardware according to the specified option * argument. If the hardware cannot support a particular option value, then * it should ignore that portion of the request. * * RETURNS: OK upon success, or EIO for invalid arguments. */ LOCAL int sngks32cOptSet ( SNGKS32C_CHAN * pChan, /* channel */ uint_t newOpts /* new options */ ) { UINT8 dataBits = 0x03; UINT8 stopBits = 0x00; BOOL hdweFlowCtrl=TRUE; BOOL rcvrEnable = TRUE; int lvl; UINT8 temp=PARITY_NONE; UINT32 result; if (pChan == NULL || newOpts & 0xffffff00) return EIO; /* do nothing if options already set */ if (pChan->options == newOpts) return OK; /* ignore requests for unsupported options */ /* decode individual request elements */ switch (newOpts & CSIZE) { case CS5: dataBits = 0x00; break; case CS6: dataBits = 0x01; break; case CS7: dataBits = 0x02; break; default: case CS8: dataBits = 0x03; break; } if (newOpts & STOPB) stopBits = 0x04; else stopBits = 0x00; switch (newOpts & (PARENB|PARODD)) { case PARENB|PARODD: /* enable odd parity */ temp=PARITY_ODD; break; case PARENB: /* enable even parity */ temp=PARITY_EVEN; break; case PARODD: /* invalid mode, not normally used. */ break; default: case 0: temp=PARITY_NONE ;/* no parity */ break; } if (newOpts & CLOCAL) { /* clocal disables hardware flow control */ hdweFlowCtrl = FALSE; } if ((newOpts & CREAD) == 0) rcvrEnable = FALSE; lvl = intLock (); /* * Reset the device according to dataBits, stopBits, hdweFlowCtrl, * rcvrEnable, and parity selections. */ SNGKS32C_SIO_REG_READ(pChan, SNGKS32C_ULCON, result); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_ULCON,(result|dataBits|temp|stopBits)); intUnlock (lvl); pChan->options = newOpts; return (OK); } /******************************************************************************* * * sngks32cIoctl - special device control * * This routine handles the IOCTL messages from the user. It supports commands * to get/set baud rate, mode(INT,POLL), hardware options(parity, number of * data bits) and modem control(RTS/CTS and DTR/DSR handshakes). * The ioctl commands SIO_HUP and SIO_OPEN are used to implement the HUPCL(hang * up on last close) function. * * As on a UNIX system, requesting a baud rate of zero is translated into * a hangup request. The DTR and RTS lines are dropped. This should cause * a connected modem to drop the connection. The SIO_HUP command will only * hangup if the HUPCL option is active. The SIO_OPEN function will raise * DTR and RTS lines whenever it is called. Use the BAUD_RATE=0 function * to hangup when HUPCL is not active. * * The CLOCAL option will disable hardware flow control. When selected, * hardware flow control is not used. When not selected hardware flow control * is based on the RTS/CTS signals. CTS is the clear to send input * from the other end. It must be true for this end to begin sending new * characters. In most drivers, the RTS signal will be assumed to be connected * to the opposite end's CTS signal and can be used to control output from * the other end. Raising RTS asserts CTS at the other end and the other end * can send data. Lowering RTS de-asserts CTS and the other end will stop * sending data. (This is non-EIA defined use of RTS). * * RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed * request. */ LOCAL int sngks32cIoctl ( SIO_CHAN * pSioChan, /* device to control */ int request, /* request code */ void * someArg /* some argument */ ) { SNGKS32C_CHAN *pChan = (SNGKS32C_CHAN *) pSioChan; int oldlevel; /* current interrupt level mask */ int arg = (int)someArg; switch (request) { case SIO_BAUD_SET: /* * like unix, a baud request for 0 is really a request to * hangup. */ if (arg == 0) return sngks32cHup (pChan); /* * Set the baud rate. Return EIO for an invalid baud rate, or * OK on success. */ if (arg < SNGKS32C_BAUD_MIN || arg > SNGKS32C_BAUD_MAX) { return (EIO); } /* Calculate the baud rate constant for the new baud rate */ switch(arg) { case 1200: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_1200|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 2400: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_2400|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 4800: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_4800|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 9600: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_9600|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 19200: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_19200|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 38400: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_38400|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 57600: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_57600|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); case 115200: /* disable interrupts during chip access */ oldlevel = intLock (); SNGKS32C_SIO_REG_WRITE(pChan,SNGKS32C_UBRDIV,SNGKS32C_CNT0_115200|SNGKS32C_CNT1_VAL); intUnlock (oldlevel); pChan->baudRate=arg; return (OK); default: return(EIO); } break; case SIO_BAUD_GET: /* Get the baud rate and return OK */ *(int *)arg = pChan->baudRate; break; case SIO_MODE_SET: /* * Set the mode (e.g., to interrupt or polled). Return OK * or EIO for an unknown or unsupported mode. */ return (sngks32cModeSet (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_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 (sngks32cOptSet (pChan, arg)); 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_HUP: /* check if hupcl option is enabled */ if (pChan->options & HUPCL) return (sngks32cHup (pChan)); return (OK); case SIO_OPEN: return (sngks32cOpen (pChan)); /* always open */ default: return (ENOSYS); } return (ENOSYS); } /******************************************************************************* * * dummyCallback - dummy callback routine * * RETURNS: ERROR. */ LOCAL STATUS dummyCallback (void) { return (ERROR); }