- /* at91UART.c - AT91RM9200 serial driver */
- /* Copyright 2003-2004 Coordinate Co., Ltd. */
- /* Copyright 1984-2002 Wind River Systems, Inc. */
- /*
- modification history
- --------------------
- 01a,28jul04,cor created from original at91Sio.c.
- */
- /*
- .SH TODO
- - Replace the documentation for this template driver with documentation
- for the driver being written.
- - Begin with an overview of the complete device. Indicate if the new driver
- only implements a sub-section of the whole device or not.
- - Describe all of the operating modes of the device, and indicate which
- ones this driver implements.
- - Document the device initialization steps to be used in the BSP to create
- and initialize the device. Document all the macros that
- can be used to customize the driver to a particular hardware environment.
- - Document anything that will help the user to understand how this device
- works and interacts with this driver.
- .SH TEMPLATE OVERVIEW
- This is a template serial driver. It can be used as a starting point
- when writing new drivers for VxWorks version 5.4 or later.
- These drivers support new functionality not found in the older style
- serial drivers. First, they provide an interface for setting hardware
- options; e.g., the number of stop bits, data bits, parity, etc.
- Second, they provide an interface for polled communication which
- can be used to provided external mode debugging (i.e., ROM monitor
- style debugging) over a serial line. Currently only asynchronous mode
- drivers are supported.
- Throughout this file the word "template" is used in place of a real
- device name, which by convention uses the first letter of the
- manufacturers name followed by the part number. For example, the
- Zilog 8530 serial device would have a data structure called a
- Z8530_CHAN, rather than TEMPLATE_CHAN.
- .SH CALLBACKS
- Servicing a "transmitter ready" interrupt involves making a callback to a
- higher level library in order to get a character to transmit.
- By default, this driver installs dummy callback routines which do
- nothing. A higher layer library that wants to use this driver (e.g., ttyDrv)
- will install its own callback routines using the SIO_INSTALL_CALLBACK
- ioctl command. (See below).
- The prototype for the transmit data callback SIO_CALLBACK_GET_TX_CHAR is:
- .CS
- int sioTxCharGet
- (
- void * arg, /@ callback argument @/
- char * pChar /@ ptr to data location @/
- )
- .CE
- This callback routine should fetch the next character to send and store it
- in the location pointed to by pChar. It returns OK to indicate that a
- character is ready and should be sent. It returns ERROR to indicate that
- no character was available and the transmitter can be placed in an idle state.
- Likewise, a receiver interrupt handler makes a callback to pass the
- character to the higher layer library. It will be called by the driver
- for each character received. This routine should capture the data and pass
- it along to other layers and eventually to the user.
- The prototype for the receive data callback SIO_CALLBACK_PUT_RCV_CHAR is:
- .CS
- void sioRxCharPut
- (
- void * arg, /@ callback argument @/
- char data /@ data byte @/
- )
- .CE
- A new error handling callback has been added SIO_CALLBACK_ERROR. This driver
- should use this callback to inform the higher layer about error conditions.
- The prototype for this callback is:
- .CS
- void sioErrorRtn
- (
- void * arg, /@ callback argument @/
- int code, /@ error code @/
- void * pData, /@ opt dev specific data @/
- int dataSize /@ opt size of data in bytes @/
- )
- .CE
- The available error codes for this callback are:
- .CS
- SIO_ERROR_FRAMING /@ (1) Framing error @/
- SIO_ERROR_PARITY /@ (2) Parity error @/
- SIO_ERROR_OFLOW /@ (3) data overflow @/
- SIO_ERROR_UFLOW /@ (4) data underflow @/
- SIO_ERROR_CONNECT /@ (5) connection made @/
- SIO_ERROR_DISCONNECT /@ (6) connection lost @/
- SIO_ERROR_NO_CLK /@ (7) clock lost @/
- SIO_ERROR_UNKNWN /@ (8) other errors @/
- .CE
- For engineering purposes, the driver may return device specific data in
- the form of a data buffer. The argument pData is the location of the buffer
- and dataSize is its size, in bytes. The data is not guaranteed to be static
- so it should be copied to a static buffer for safekeeping.
- .SH MODES
- Ideally the driver should support both polled and interrupt modes, and be
- capable of switching modes dynamically. However this is not required.
- VxWorks will be able to support a tty device on this driver even if
- the driver only supports interrupt mode.
- Polled mode is provided solely for WDB system mode usage. Users can use
- the polled mode interface directly, but there is no clear reason for doing so.
- Normal access to SIO devices through ttyDrv only uses interrupt mode.
- For dynamically switchable drivers, be aware that the driver may be
- asked to switch modes in the middle of its input ISR. A driver‘s input ISR
- will look something like this:
- inChar = *pDev->dr; /@ read a char from data register @/
- *pDev->cr = GOT_IT; /@ acknowledge the interrupt @/
- pDev->putRcvChar (...); /@ give the character to the higher layer @/
- If this channel is used as a communication path to an external mode
- debug agent, and if the character received is a special "end of packet"
- character, then the agent‘s callback will lock interrupts, switch
- the device to polled mode, and use the device in polled mode for awhile.
- Later on the agent will unlock interrupts, switch the device back to
- interrupt mode, and return to the ISR.
- In particular, the callback can cause two mode switches, first to polled mode
- and then back to interrupt mode, before it returns.
- This may require careful ordering of the callback within the interrupt
- handler. For example, you may need to acknowledge the interrupt before
- invoking the callback.
- .SH USAGE
- The driver is typically called only by the BSP. The directly callable
- routines in this module are templateSioCreate(), templateSioDestroy().
- .SH BSP
- By convention all the BSP-specific serial initialization is performed in
- a file called sysSerial.c, which is #include‘ed by sysLib.c.
- This driver can be customized by redefining the macros SYS_SIO_READ8 and
- SYS_SIO_WRITE8. These two macros are used for all accesses to the
- actual chip. If not defined, the source code will assume a simple memory
- mapped device using byte read/write access to all registers.
- The macros SYS_SIO_INT_CONNECT, SYS_SIO_INT_DISCONNECT, SYS_SIO_INT_ENABLE,
- and SYS_SIO_PROBE can be redefined by the BSP to perform basic low level
- routines with the same calling sequence as intConnect(), intConnect(),
- intEnable(), and vxMemProbe().
- .SH TESTING
- The interrupt driven interface can be tested in the usual way; VxWorks
- prints to the serial console when it comes up, so seeing the usual VxWorks
- output on power-up shows that the driver is basically working.
- The VxWorks portkit test can be used to perform a more strenuous test.
- The polled interface should be easy enough to verify - you should be able
- to call the channels SIO_MODE_SET ioctl to put it in polled mode. Note
- that the usual print tools won‘t work with a serial channel in polled mode.
- Some agent has to perform a polling loop to handle input/output on a
- character by character basis. It is not automatic. The WDB agent
- performs its own polling loop when it switches the WDB serial line into
- polled mode.
- The dynamic mode switching can be verified using the tornado tools.
- Reconfigure the agent to use the WDB_COMM_UDLP_SLIP communication path (see
- the Configuration section in the VxWorks run-time Guide for details).
- Start VxWorks, and connect the tgtsvr to the agent using the wdbserial
- backend (see the Tornado Users Guide for details).
- Start the wtxtcl shell as follows:
- % wtxtcl
- From the tcl prompt, attach to the target server:
- wtxtcl.ex> wtxToolAttach <tgtsvr name>
- Tell the agent to switch to external mode, and verify the reply is OK (0).
- wtxtcl.ex>wtxAgentModeSet 2
- 0
- Ask the agent to suspend the system (the request will reach the agent in
- interrupt mode, but the reply will be sent in polled mode):
- wtxtcl.ex>wtxContextSuspend 0 0
- 0
- At this point the target will be suspended. The console should apprear
- frozen (if the board has a console device), and you will not be able to
- "ping" the target‘s network interface.
- Resume the target:
- wtxtcl.ex>wtxContextResume 0 0
- 0
- The target should now be running again, so you should be able to type into
- the console (if the board has a console device) and ping the targets network
- interface from the host.
- .SH INCLUDE FILES:
- at91Sio.h sioLib.h
- */
- #include "vxWorks.h"
- #include "intLib.h"
- #include "errnoLib.h"
- #include "iosLib.h" /* For S_iosLib_DEVICE_NOT_FOUND */
- #include "cacheLib.h"
- #include "stdlib.h" /* malloc/free */
- #include "stdio.h" /* for printf */
- #include "vxLib.h" /* for vxMemProbe */
- #include "at91.h"
- #include "at91rm9200.h"
- #include "at91If.h"
- #include "at91Sio.h"
- #include "arch\arm\ivarm.h"
- #define DEFAULT_BAUD 9600
- /* channel control register (write) definitions */
- #if 0
- /* TODO - These are just made up bit defines for a mythical device! */
- #define TEMPLATE_RESET_CHIP 0x07 /* reset all */
- #define TEMPLATE_RESET_TX 0x01 /* reset the transmitter */
- #define TEMPLATE_RESET_ERR 0x02 /* reset error condition */
- #define TEMPLATE_RESET_INT 0x04 /* acknoledge the interrupt */
- #define TEMPLATE_INT_ENABLE 0x08 /* enable interrupts */
- #define TEMPLATE_TX_ENABLE 0x10 /* enable interrupts */
- #define TEMPLATE_RX_ENABLE 0x20 /* enable interrupts */
- /* channel status register (read) definitions */
- #define TEMPLATE_CR_OKAY 0x00 /* no error conditions */
- #define TEMPLATE_CR_TX_READY 0x01 /* txmitter ready for another char */
- #define TEMPLATE_CR_TX_ERROR 0x04 /* txmitter int enable */
- #define TEMPLATE_CR_RX_AVAIL 0x10 /* character has arrived */
- #define TEMPLATE_CR_RX_ERROR 0x40 /* receiver error */
- /* channel modem status register definitions */
- #define TEMPLATE_MSR_RTS 0x1 /* RTS signal asserted */
- #define TEMPLATE_MSR_DTR 0x2 /* DTR signal asserted */
- #define TEMPLATE_MSR_DSR 0x4 /* DSR signal asserted */
- #define TEMPLATE_MSR_CTS 0x8 /* CTS signal asserted */
- #define TEMPLATE_MSR_CD 0x10 /* CD signal asserted */
- /* input and output signals */
- #define TEMPLATE_ISIG_MASK (SIO_MODEM_CTS|SIO_MODEM_DSR|SIO_MODEM_CD)
- #define TEMPLATE_OSIG_MASK (SIO_MODEM_RTS|SIO_MODEM_DTR)
- /* channel modem control register definitions */
- #define TEMPLATE_MC_RTS 0x1 /* enable RTS */
- #define TEMPLATE_MC_DTR 0x2 /* enable DTR */
- #endif
- #define AT91_BAUD_MIN 110
- #define AT91_BAUD_MAX 921600
- /* Hardware abstraction macros */
- #if 0
- /* Macros from BSP */
- #define SYS_SIO_READ8(addr, pData) \
- (*pData = *(UINT8 *)(addr))
- #define SYS_SIO_WRITE8(addr, data) \
- (*(UINT8 *)addr = data)
- #define SYS_SIO_INT_CONNECT(vec, rtn, arg) \
- intConnect ((VOIDFUNCPTR *)vec, (VOIDFUNCPTR)rtn, (int)arg)
- #define SYS_SIO_INT_DISCONNECT(vec, rtn, arg) \
- intConnect ((VOIDFUNCPTR *)vec, NULL, 0)
- #define SYS_SIO_INT_ENABLE(level) \
- intEnable (level)
- #define SYS_SIO_PROBE(addr, mode, size, pData) \
- vxMemProbe (addr, mode, size, pData)
- /* #define CACHE_PIPE_FLUSH() */
- /* Local driver abstractions, following bus/adaptor model */
- #define TEMPLATE_SIO_READ8(pChan, reg, result) \
- SYS_SIO_READ8(((pChan->ioBase) + reg),result)
- #define TEMPLATE_SIO_WRITE8(pChan, reg, data) \
- SYS_SIO_WRITE8(((pChan->ioBase) + reg),data)
- #define TEMPLATE_SIO_INT_CONNECT(pChan, vec, rtn, arg) \
- do { \
- SYS_SIO_INT_CONNECT((pChan->vecBase) + vec, rtn, arg); \
- SYS_SIO_INT_ENABLE(pChan->intLevel); \
- } while (0)
- #define TEMPLATE_INT_DISCONNECT(pChan, vec, rtn, arg) \
- SYS_SIO_INT_DISCONNECT(((pChan)->vecBase + vec), rtn, arg)
- /* Do NOT disable interrupt level for disconnect */
- #define TEMPLATE_PROBE(pChan, offset, dir, size, ptr) \
- SYS_SIO_PROBE((char *)((pChan)->ioBase + offset), dir, size, ptr)
- #define TEMPLATE_PIPE_FLUSH(pChan) \
- CACHE_PIPE_FLUSH()
- #endif
- /* forward static declarations */
- LOCAL int at91TxStartup (SIO_CHAN * pSioChan);
- LOCAL int at91CallbackInstall (SIO_CHAN *pSioChan, int callbackType,
- STATUS (*callback)(void *,...), void *callbackArg);
- LOCAL int at91PollOutput (SIO_CHAN *pSioChan, char outChar);
- LOCAL int at91PollInput (SIO_CHAN *pSioChan, char *thisChar);
- LOCAL int at91Ioctl (SIO_CHAN *pSioChan, int request, void *arg);
- LOCAL STATUS at91DummyTxCallback (void *, char *);
- LOCAL void at91DummyRxCallback (void *, char);
- LOCAL void at91DummyErrCallback (void *, int, void *, int);
- LOCAL void at91UARTIntRx (AT91_UART_CHAN * pChan);
- LOCAL void at91UARTIntTx (AT91_UART_CHAN * pChan);
- LOCAL STATUS at91Probe (AT91_UART_CHAN * pChan);
- /*
- LOCAL STATUS at91Verify (AT91_UART_CHAN *pChan);
- LOCAL int at91MstatGet (AT91_UART_CHAN *pChan);
- LOCAL int at91MstatSetClr (AT91_UART_CHAN *pChan, UINT bits, BOOL setFlag);
- */
- /* local variables */
- LOCAL SIO_DRV_FUNCS at91UARTDrvFuncs =
- {
- at91Ioctl,
- at91TxStartup,
- at91CallbackInstall,
- at91PollInput,
- at91PollOutput
- };
- /******************************************************************************
- *
- * at91UARTDevInit - initialise an AT91_SIO channel
- *
- * This routine initialises some SIO_CHAN function pointers and then resets
- * the chip to a quiescent state. Before this routine is called, the BSP
- * must already have initialised all the device addresses, etc. in the
- * AT91_UART_CHAN structure.
- *
- * RETURNS: N/A
- */
- void at91UARTDevInit
- (
- AT91_UART_CHAN * pChan /* ptr to AT91_UART_CHAN describing this channel */
- )
- {
- AT91PS_USART pUsart; /* point to UART register index by ioBase of pChan */
- AT91PS_PIO pPIOA, pPIOB; /* point to PIO Controller A, B */
- AT91_UART_PARAS *pParas;
- int oldIntLvl;
- if (pChan != NULL)
- {
- pChan->sio.pDrvFuncs = &at91UARTDrvFuncs;
- /* install dummy driver callbacks */
- pChan->getTxChar = at91DummyTxCallback;
- pChan->putRcvChar = at91DummyRxCallback;
- pChan->errorRtn = at91DummyErrCallback;
- pChan->intConnect = FALSE; /* int‘s not connected yet */
- /* setting polled mode is one way to make the device quiet */
- pChan->mode = SIO_MODE_POLL; /* setting mode to poll mode */
- if (at91Probe (pChan) == OK)
- {
- oldIntLvl = intLock();
- pParas = pChan->pUart;
- pChan->ioBase = pParas->ioBase; /* set parameter of pParas to pChan for easy usage */
- pUsart = (AT91PS_USART)(pParas->ioBase);
- pPIOA = (AT91PS_PIO)(AT91RM9200_PIOA_BASE_ADDR);
- pPIOB = (AT91PS_PIO)(AT91RM9200_PIOB_BASE_ADDR);
- *(volatile unsigned int *)AT91RM9200_PMC_PCER = 1 << pParas->uartId; /* enable clock */
- pPIOA->PIO_ASR = pParas->PIOA_ASR;
- pPIOA->PIO_BSR = pParas->PIOA_BSR;
- pPIOA->PIO_PDR = pParas->PIOA_ASR | pParas->PIOA_BSR;
- pPIOB->PIO_ASR = pParas->PIOA_ASR;
- pPIOB->PIO_BSR = pParas->PIOA_BSR;
- pPIOB->PIO_PDR = pParas->PIOB_ASR | pParas->PIOB_BSR;
- pUsart->US_IDR = -1; /* disable all USART interrupts */
- /* reset & disble transmit and receive */
- pUsart->US_CR = AT91RM9200_US_CR_RSTRX | AT91RM9200_US_CR_RSTTX | \
- AT91RM9200_US_CR_RXDIS | AT91RM9200_US_CR_TXDIS;
- pUsart->US_BRGR = AT91_MASTER_CLOCK / (pParas->baudRate) / 16; /* 115200 baud with 18.432 Mhz Crystal */
- pUsart->US_RTOR = AT91_USART_RX_TIMEOUT; /* Receiver Time-out Register */
- pUsart->US_TTGR = 0; /* Transmitter timeguart is disabled */
- pUsart->US_FIDI = 0; /* in ISO7816 mode, BRG generates no signal */
- /* Disable PDC Channels for DBGU and Initial the State of it */
- pUsart->US_PTCR = AT91RM9200_PDC_PTCR_TXTDIS | AT91RM9200_PDC_PTCR_RXTDIS;
- pUsart->US_TNPR = 0;
- pUsart->US_TNCR = 0; /* clear out next transmit counts */
- pUsart->US_RNPR = 0;
- pUsart->US_RNCR = 0; /* clear out next receive counts */
- pUsart->US_TPR = 0;
- pUsart->US_TCR = 0; /* clear out transmit counts */
- pUsart->US_RPR = 0;
- pUsart->US_RCR = 0; /* clear out receive counts */
- pUsart->US_MR = pParas->uartOption; /* default mode */
- intUnlock(oldIntLvl);
- pChan->mode = SIO_MODE_INT;
- /* Enable transmit and received of UART Device */
- pUsart->US_CR = AT91RM9200_US_CR_RXEN | AT91RM9200_US_CR_TXEN;
- }
- else
- {
- /* Whoops, device is not there! */
- free ((char *)pChan);
- errnoSet (S_iosLib_DEVICE_NOT_FOUND);
- return;
- }
- }
- return;
- }
- /*******************************************************************************
- *
- * at91UARTInt - handle an AT91RM9200 UART interrupt
- *
- * This routine is called to handle AT91RM9200 UART interrupts.
- */
- void at91UARTInt
- (
- AT91_UART_CHAN *pChan
- )
- {
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- UINT32 status;
- int errorCode = SIO_ERROR_NONE;
- status = pUsart->US_CSR;
- if (status)
- {
- /* we can make below process several times when TXRDY or RXRDY is there */
- if (status & (AT91RM9200_US_SR_RXRDY))
- at91UARTIntRx (pChan);
- /* Check for error conditions */
- if (status & (AT91RM9200_US_SR_PARE | AT91RM9200_US_SR_FRAME | AT91RM9200_US_SR_OVRE))
- {
- /*
- * Determine precise error condition and perform
- * recovery actions.
- */
- pUsart->US_CR = AT91RM9200_US_CR_RSTSTA;
- /*
- * If needed, you should acknowledge or reset the interrupt source
- * as soon as possible, usually before passing any error conditions
- * upstream.
- */
- if (status & (AT91RM9200_US_SR_PARE))
- {
- errorCode = SIO_ERROR_PARITY;
- }
- else if (status & (AT91RM9200_US_SR_FRAME))
- {
- errorCode = SIO_ERROR_FRAMING;
- }
- if (errorCode != SIO_ERROR_NONE)
- (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);
- if (status & (AT91RM9200_US_SR_OVRE))
- {
- errorCode = SIO_ERROR_OFLOW;
- (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);
- }
- }
- if (status & (AT91RM9200_US_SR_TXRDY))
- at91UARTIntTx (pChan);
- }
- }
- /******************************************************************************
- *
- * at91UARTIntRx - handle a channel‘s receive-character interrupt
- *
- * RETURNS: N/A
- */
- LOCAL void at91UARTIntRx
- (
- AT91_UART_CHAN * pChan /* channel generating the interrupt */
- )
- {
- char inChar; /* receive data */
- UINT32 rxStatus = 0; /* receive status */
- /*
- STATUS status = OK;
- int errorCode = SIO_ERROR_NONE;
- */
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- /*
- *
- * Get status and data from the device. Determine if valid data is ready
- * or not.
- *
- * For PCI devices, do an immediate return if device is not asserting
- * an interrupt.
- */
- rxStatus = pUsart->US_CSR;
- while (rxStatus & AT91RM9200_US_SR_RXRDY)
- {
- inChar = pUsart->US_RHR;
- /* RXRDY bit in US_CSR will be clear when RHR is read */
- /* send data character upstream */
- (*pChan->putRcvChar) (pChan->putRcvArg, inChar);
- if (pChan->mode != SIO_MODE_INT) break;
- rxStatus = pUsart->US_CSR;
- }
- #if 0 /* will be processed in at91UARTIntErr */
- if (status == ERROR)
- {
- /* send error notification upstream */
- (*pChan->errorRtn) (pChan->errorArg, SIO_ERROR_UNKNWN, NULL, 0);
- }
- #endif
- #if 0 /* Keyboard emulation code */
- /*
- * TODO - For a keyboard type device we would map the raw scan code
- * to ASCII, or other mapping. Do that here.
- */
- if (pChan->scanMode == SIO_KYBD_MODE_ASCII)
- inChar = templateAsciiTbl[(UINT8)inChar];
- #endif
- }
- /******************************************************************************
- *
- * at91UARTIntTx - handle a channels transmitter-ready interrupt
- *
- * RETURNS: N/A
- */
- LOCAL void at91UARTIntTx
- (
- AT91_UART_CHAN *pChan /* channel generating the interrupt */
- )
- {
- char outChar;
- UINT32 txStatus; /* status of transmit */
- /* BOOL txReady = TRUE; */
- int errorCode = SIO_ERROR_NONE;
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase);; /* point to UART register index by ioBase of pChan */
- /*
- * Check the Tx status
- *
- * For PCI devices, do an immediate return if device is not asserting
- * an interrupt.
- */
- #if 0
- /* Check for error conditions */
- if (crData & TEMPLATE_CR_TX_ERROR)
- {
- /*
- * TODO - Typically you should determine the precise error condition
- * and perform all recovery operations here.
- */
- TEMPLATE_SIO_WRITE8 (pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_TX);
- errorCode = SIO_ERROR_UNKNWN;
- txReady = TRUE; /* set to false if xmitter is not ready now */
- }
- #endif
- /*
- * If transmitter is okay and ready to send, lets see if there is a
- * data character ready to be sent.
- *
- * If there‘s a character to transmit then write it out, else reset (idle)
- * the transmitter. For chips with output FIFO‘s it is more efficient
- * to fill the entire FIFO here.
- */
- txStatus = pUsart->US_CSR;
- if (txStatus & AT91RM9200_US_SR_TXRDY)
- {
- if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
- {
- /* Output data to device. */
- pUsart->US_THR = outChar;
- /* need to insert a wait time for transmit finished ? */
- txStatus = pUsart->US_CSR;
- /*
- * If a device error occurs at this point, then
- * isolate the precise error type and try to recover.
- */
- }
- else
- {
- /*
- * There is no more data to send.
- *
- * Put XMTR in an idle state. Higher layer
- * will call TxStartup entry to resume xmit operations.
- */
- pUsart->US_IDR = AT91RM9200_US_INT_TXRDY;
- /*
- pUsart->US_CR = AT91RM9200_US_CR_TXDIS | AT91RM9200_US_CR_RSTTX; */ /* disable transmit */
- /* break; */
- }
- }
- /*
- * If needed, you should acknowledge or reset the interrupt source
- * as soon as possible, usually before passing any error conditions
- * upstream.
- */
- /* US_TXRDY will be cleared when char is sent */
- /* Pass any errorCodes upstream. */
- if (errorCode != SIO_ERROR_NONE)
- {
- (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);
- }
- }
- #if 0
- /******************************************************************************
- *
- * at91UARTIntErr - handle a channels error interrupt
- *
- * RETURNS: N/A
- */
- LOCAL void at91UARTIntErr
- (
- AT91_UART_CHAN * pChan /* channel generating the interrupt */
- )
- {
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase);; /* point to UART register index by ioBase of pChan */
- UINT32 errStatus;
- errStatus = pUsart->US_CSR;
- /*
- * Determine the precise error condition and perform recovery
- * operations.
- *
- * For PCI devices, do an immediate return if device is not asserting
- * an interrupt.
- */
- if (errStatus & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE)
- {
- }
- }
- #endif
- /******************************************************************************
- *
- * templateTxStartup - start the interrupt transmitter
- *
- * This routine exits to inform the device to start transmitting data again.
- * The actual data will be obtained by calling the TxCharGet callback routine.
- *
- * This routine is usually just the same as the tx interrupt routine. This
- * routine runs at task level context and does not have to be interrupt safe.
- *
- * RETURNS: OK on success, ENOSYS if the device is polled-only, or
- * EIO on hardware error.
- */
- LOCAL int at91TxStartup
- (
- SIO_CHAN * pSioChan /* channel to start */
- )
- {
- AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- /* char outChar; */
- /* This routine should only be called while in interrupt mode */
- /* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
- NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
- NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
- NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
- */
- /* pChan->mode = SIO_MODE_POLL; */
- if (pChan->mode == SIO_MODE_INT)
- {
- #if 0
- if (pChan->options & CLOCAL)
- {
- /* No modem control - start immediately */
- }
- else
- {
- /*
- * Modem controls are active.
- *
- * If CTS is high, we can start immediately so just enable
- * the TX interrupt.
- *
- * If CTS is low, then we cannot send now. The driver
- * should be set up to generate a TX interrupt when the CTS
- * line returns to the active state.
- */
- }
- /*
- * Enable the correct interrupts. A TX interrupt should either
- * occur immediately, or later when CTS becomes active. That will start
- * the flow of data.
- *
- * There are two usual methods here. The first is to just enable
- * TX interrupts, which should cause an immediate TX interrupt, which
- * will begin fetching and sending characters.
- *
- * The second method is to call the getTxChara callback here, put
- * the data to the transmitter directly, and then to enable TX
- * interrupts to fetch and send additional characters.
- */
- #endif
- #if 0
- if ((pUsart->US_CSR & AT91C_US_TXRDY) && \
- ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR))
- {
- /* Output data to device. */
- pUsart->US_THR = outChar;
- /*
- * If a device error occurs at this point, then
- * isolate the precise error type and try to recover.
- */
- }
- #endif
- /* intEnable(pChan->intLevel); */
- /* pUsart->US_CR = AT91C_US_TXEN; */
- pUsart->US_IER = AT91RM9200_US_INT_TXRDY; /* we need set it again here ? */
- return OK;
- }
- else
- /*
- while ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
- {
- while (EAGAIN == at91PollOutput ((SIO_CHAN *)pChan, outChar));
- }
- */
- return ENOSYS; /* Not valid for polled mode operation */
- return (OK);
- }
- /******************************************************************************
- *
- * at91CallbackInstall - 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 at91CallbackInstall
- (
- SIO_CHAN * pSioChan, /* channel */
- int callbackType, /* type of callback */
- STATUS (*callback)(void *,...), /* callback */
- void * callbackArg /* parameter to callback */
- )
- {
- AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;
- switch (callbackType)
- {
- case SIO_CALLBACK_GET_TX_CHAR:
- pChan->getTxChar = (STATUS (*)(void *, char *))callback;
- pChan->getTxArg = callbackArg;
- return (OK);
- case SIO_CALLBACK_PUT_RCV_CHAR:
- pChan->putRcvChar = (void (*)(void *, char))callback;
- pChan->putRcvArg = callbackArg;
- return (OK);
- case SIO_CALLBACK_ERROR:
- pChan->errorRtn = (void (*)(void *, int, void *, int))callback;
- pChan->errorArg = callbackArg;
- return (OK);
- default:
- return (ENOSYS);
- }
- }
- /*******************************************************************************
- *
- * templatePollOutput - output a character in polled mode
- *
- * Polled mode operation takes place without any kernel or other OS
- * services available. Use extreme care to insure that this code does not
- * call any kernel services. Polled mode is only for WDB system mode use.
- * Kernel services, semaphores, tasks, etc, are not available during WDB
- * system 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 at91PollOutput
- (
- SIO_CHAN * pSioChan,
- char outChar
- )
- {
- AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- UINT32 status;
- /* is the transmitter ready to accept a character? */
- /* Read TX device status */
- status = pUsart->US_CSR;
- /* determine if transmitter is ready */
- if (0x00 == (status & (AT91RM9200_US_SR_TXRDY)))
- /* device is busy, try again later */
- return (EAGAIN);
- /* transmit the character */
- pUsart->US_THR = (AT91_REG)outChar;
- return (OK);
- }
- /******************************************************************************
- *
- * at91PollInput - poll the device for input
- *
- * Polled mode operation takes place without any kernel or other OS
- * services available. Use extreme care to insure that this code does not
- * call any kernel services. Polled mode is only for WDB system mode use.
- * Kernel services, semaphores, tasks, etc, are not available during WDB
- * system mode.
- *
- * 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 at91PollInput
- (
- SIO_CHAN * pSioChan,
- char * thisChar
- )
- {
- AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- UINT32 status;
- /* Read RX device status */
- status = pUsart->US_CSR;
- /* Check if receive data is available */
- if (0x00 == (status & (AT91RM9200_US_SR_RXRDY)))
- {
- return EAGAIN; /* no input available at this time */
- }
- /* Check for receive error conditions */
- if (0x00 != (status & (AT91RM9200_US_SR_PARE | AT91RM9200_US_SR_FRAME | AT91RM9200_US_SR_OVRE)))
- {
- /* Decode and handle the specific error condition */
- pUsart->US_CR = AT91RM9200_US_CR_RSTSTA; /* reset receive of USART to clear error */
- /* Do NOT call the error callback routine, just return EIO */
- return EIO;
- }
- /* read character, store it, and return OK */
- *thisChar = (char)(pUsart->US_RHR);
- return (OK);
- }
- /******************************************************************************
- *
- * at91ModeSet - toggle between interrupt and polled mode
- *
- * RETURNS: OK on success, EIO on unsupported mode.
- */
- LOCAL int at91ModeSet
- (
- AT91_UART_CHAN * pChan, /* channel */
- uint_t newMode /* new mode */
- )
- {
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- AT91_UART_PARAS *pParas = (AT91_UART_PARAS *)(pChan->pUart);
- int oldIntLvl;
- if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
- return (EIO);
- oldIntLvl = intLock();
- /*
- * use this function will made all the action done in
- * at91IosDevInit be cancelled, so we can‘t do it now
- pUsart->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX;
- */
- if (pChan->mode == SIO_MODE_INT)
- {
- /* switch device to interrupt mode */
- if (pChan->intConnect == FALSE)
- {
- /* interconnect ISR to intvector */;
- intConnect (INUM_TO_IVEC(pParas->vector), at91UARTInt, (int)pChan);
- pChan->intConnect = TRUE;
- }
- /* enable interrupt of device */
- pUsart->US_IER = AT91RM9200_US_INT_RXRDY | AT91RM9200_US_INT_PARE |AT91RM9200_US_INT_FRAME | AT91RM9200_US_INT_OVRE;
- pUsart->US_IDR = AT91RM9200_US_INT_TXRDY;
- /* we only enable receive and error interrupt
- pUsart->US_IER = AT91RM9200_US_INT_RXRDY | AT91RM9200_US_INT_RXRDY |AT91RM9200_US_INT_PARE | AT91RM9200_US_INT_FRAME |AT91RM9200_US_INT_OVRE;
- */
- intEnable (pParas->intLevel);
- }
- else
- {
- /* switch device to polled mode */
- /* disable interrupt of device */
- pUsart->US_IDR = -1; /* disable all interrupt */
- intDisable (pParas->intLevel);
- }
- /* activate the new mode */
- pChan->mode = newMode;
- intUnlock(oldIntLvl);
- return (OK);
- }
- #if 0
- /*******************************************************************************
- *
- * templateHup - hang up the modem control lines
- *
- * Resets the RTS and DTR signals.
- *
- * RETURNS: OK always.
- */
- LOCAL STATUS at91Hup
- (
- AT91_UART_CHAN * pChan /* pointer to channel */
- )
- {
- /*
- * TODO - Use global intLock if lockout time will be very short. If not,
- * use a device specific lockout that will not damage overall system
- * latency.
- */
- at91MstatSetClr (pChan,(SIO_MODEM_RTS|SIO_MODEM_DTR), FALSE);
- return (OK);
- }
- /*******************************************************************************
- *
- * at91Open - Set the modem control lines
- *
- * Set the modem control lines(RTS, DTR) TRUE if not already set.
- *
- * RETURNS: OK
- */
- LOCAL STATUS at91Open
- (
- AT91_UART_CHAN * pChan /* pointer to channel */
- )
- {
- /*
- * TODO - Use global intLock if lockout time will be very short. If not,
- * use a device specific lockout that will not damage overall system
- * latency.
- */
- at91MstatSetClr (pChan, (SIO_MODEM_RTS|SIO_MODEM_DTR), TRUE);
- return (OK);
- }
- #endif
- /******************************************************************************
- *
- * at91OptSet - 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 at91OptSet
- (
- AT91_UART_CHAN * pChan, /* channel */
- uint_t newOpts /* new options */
- )
- {
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- AT91_UART_PARAS *pParas = (AT91_UART_PARAS *)(pChan->pUart);
- int uartHwOptions = pParas->uartOption;
- /*
- BOOL hdweFlowCtrl=TRUE;
- BOOL rcvrEnable = TRUE;
- */
- int oldIntLvl;
- if (pChan == NULL || newOpts & 0xffffff00)
- return EIO;
- /* do nothing if options already set */
- if (pParas->uartOption== newOpts)
- return OK;
- /* ignore requests for unsupported options */
- /* decode individual request elements */
- uartHwOptions &= ~(AT91RM9200_US_MR_CHRL);
- switch (newOpts & CSIZE)
- {
- case CS5:
- uartHwOptions |= AT91RM9200_US_MR_CHRL_5_BITS;
- break;
- case CS6:
- uartHwOptions |= AT91RM9200_US_MR_CHRL_6_BITS;
- break;
- case CS7:
- uartHwOptions |= AT91RM9200_US_MR_CHRL_7_BITS;
- break;
- default:
- case CS8:
- uartHwOptions |= AT91RM9200_US_MR_CHRL_8_BITS;
- break;
- }
- uartHwOptions &= ~(AT91RM9200_US_MR_NBSTOP);
- if (newOpts & STOPB)
- /* 2 bits stop bit */
- uartHwOptions |= AT91RM9200_US_MR_NBSTOP_2_BIT;
- else
- /* 1 bit stop bit */
- uartHwOptions |= AT91RM9200_US_MR_NBSTOP_1_BIT;
- uartHwOptions &= ~(AT91RM9200_US_MR_PAR);
- switch (newOpts & (PARENB|PARODD))
- {
- case PARENB|PARODD:
- /* enable odd parity */
- uartHwOptions |= AT91RM9200_US_MR_PAR_ODD;
- break;
- case PARENB:
- /* enable even parity */
- uartHwOptions |= AT91RM9200_US_MR_PAR_EVEN;
- break;
- case PARODD:
- /* invalid mode, not normally used. */
- uartHwOptions |= AT91RM9200_US_MR_PAR_MULTI_DROP;
- break;
- default:
- case 0:
- /* no parity */;
- uartHwOptions |= AT91RM9200_US_MR_PAR_NONE;
- break;
- }
- if (newOpts & CLOCAL)
- {
- /* clocal disables hardware flow control */
- uartHwOptions &= ~(AT91RM9200_US_MR_USMODE);
- uartHwOptions |= AT91RM9200_US_MR_USMODE_NORMAL;
- }
- else
- {
- /* enable hardware flow control */
- uartHwOptions &= ~(AT91RM9200_US_MR_USMODE);
- uartHwOptions |= AT91RM9200_US_MR_USMODE_HWHSH;
- uartHwOptions |= AT91RM9200_US_MR_USMODE_MODEM;
- }
- if ((newOpts & CREAD) == 0)
- pUsart->US_CR = AT91RM9200_US_CR_RXDIS;
- else
- pUsart->US_CR = AT91RM9200_US_CR_RXEN;
- oldIntLvl = intLock ();
- /*
- * Reset the device according to uartHwOptions
- */
- pUsart->US_MR = uartHwOptions;
- intUnlock (oldIntLvl);
- /*
- * Be sure that pChan->options reflects the actual
- * hardware settings. If 5 data bits were requested, but unsupported,
- * then be sure pChan->options reflects the actual number of data bits
- * currently selected.
- */
- /*
- * we store register setting in pParas->uartOption
- * and software setting in pChan->options
- */
- pParas->uartOption = uartHwOptions;
- pChan->options = newOpts;
- return (OK);
- }
- /*******************************************************************************
- *
- * at91Ioctl - 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 at91Ioctl
- (
- SIO_CHAN * pSioChan, /* device to control */
- int request, /* request code */
- void * someArg /* some argument */
- )
- {
- AT91_UART_CHAN *pChan = (AT91_UART_CHAN *) pSioChan;
- AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */
- AT91_UART_PARAS *pParas = (AT91_UART_PARAS *)(pChan->pUart);
- int oldLevel; /* current interrupt level mask */
- int baudConstant;
- int arg = (int)someArg;
- /* TEMPLATE_PIPE_FLUSH(pChan); */
- switch (request)
- {
- case SIO_BAUD_SET:
- /*
- * like unix, a baud request for 0 is really a request to hangup.
- */
- if (arg == 0)
- return (EIO);
- /* return (at91Hup (pChan)); */
- /*
- * Set the baud rate. Return EIO for an invalid baud rate, or
- * OK on success.
- */
- if (arg < AT91_BAUD_MIN || arg > AT91_BAUD_MAX)
- {
- return (EIO);
- }
- /* Calculate the baud rate constant for the new baud rate */
- baudConstant = AT91_MASTER_CLOCK / arg / 16;
- /* disable interrupts during chip access */
- oldLevel = intLock ();
- pUsart->US_BRGR = baudConstant;
- intUnlock (oldLevel);
- pParas->baudRate = arg;
- return (OK);
- case SIO_BAUD_GET:
- *(int *)someArg = pParas->baudRate;
- 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 (at91ModeSet (pChan, arg));
- case SIO_MODE_GET:
- /* Get the current mode and return OK. */
- *(int *)someArg = pChan->mode;
- return (OK);
- case SIO_AVAIL_MODES_GET:
- /* TODO - set the available modes and return OK. */
- *(int *)someArg = 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 (at91OptSet (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 *)someArg = pChan->options;
- return (OK);
- #if 0
- case SIO_HUP:
- /* check if hupcl option is enabled */
- if (pChan->options & HUPCL)
- return (at91Hup (pChan));
- return (OK);
- case SIO_OPEN:
- return (at91Open (pChan)); /* always open */
- #endif
- #if 0 /* TODO - optional modem control line support */
- /*
- * These new ioctl commands are for monitoring and setting the
- * state of the modem control lines under user control. The
- * return values from these calls inform the user about which
- * control lines are inputs and which are outputs. Basically
- * this lets the user know if the device is wired for DTE or
- * DCE configuration. It also informs the user if any signals
- * are missing altogether.
- */
- case SIO_MSTAT_GET:
- return templateMstatGet(pChan);
- case SIO_MCTRL_BITS_SET:
- return templateMstatSetClr (pChan, arg, TRUE);
- case SIO_MCTRL_BITS_CLR:
- return templateMstatSetClr (pChan, arg, FALSE);
- /*
- * The ISIG and OSIG masks tell the user which signals are actually
- * outputs and which aren‘t. In our case here, we assume the device
- * is DTE mapped with DTR and RTS as outputs. DSR and CTS as inputs.
- * This template driver doesn‘t support RI.
- */
- case SIO_MCTRL_OSIG_MASK:
- *(int *)someArg = TEMPLATE_OSIG_MASK;
- break;
- case SIO_MCTRL_ISIG_MASK:
- *(int *)someArg = TEMPLATE_ISIG_MASK;
- break;
- #endif /* optional Modem control line support */
- #if 0 /* TODO - optional keyboard scan code support */
- /*
- * The following new ioctl commands are meant only for keyboard
- * input devices to use. These allow the user to specify and
- * examine the type of keyboard character mapping to use. The
- * possible types are NONE (raw scan codes), ASCII (default ascii
- * mappings, and UNICODE for standard 16 bit unicode mappings.
- *
- * Our template driver supports only raw and ascii modes.
- */
- case SIO_KYBD_MODE_SET:
- switch (arg)
- {
- case SIO_KYBD_MODE_RAW:
- case SIO_KYBD_MODE_ASCII:
- break;
- case SIO_KYBD_MODE_UNICODE:
- return ENOSYS; /* template doesn‘t support unicode */
- }
- pChan->scanMode = arg;
- return OK;
- case SIO_KYBD_MODE_GET:
- *(int *)someArg = pChan->scanMode;
- return OK;
- #endif /* optional keyboard scan code support */
- default:
- return ENOSYS;
- }
- return OK;
- }
- /*******************************************************************************
- *
- * dummyTxCallback - dummy Tx callback routine
- *
- * RETURNS: ERROR.
- */
- LOCAL STATUS at91DummyTxCallback
- (
- void * callbackArg, /* argument registered with callback */
- char * pChara /* ptr to data location */
- )
- {
- static BOOL doit = TRUE;
- /*
- * TODO - Until an upstream module connects to this device, there
- * is no data available to send. We should only be concerned
- * if this callback is being called repeatedly and often. That
- * could indicate an interrupt servicing problem of some kind.
- */
- if (doit)
- {
- printf ("Dummy txCallback: 0x%x 0x%x\n",
- (int)callbackArg, (int)pChara);
- doit = FALSE;
- }
- return (ERROR);
- }
- /*******************************************************************************
- *
- * dummyRxCallback - dummy Rx callback routine
- *
- * RETURNS: N/A.
- * ARGSUSED
- */
- LOCAL void at91DummyRxCallback
- (
- void * callbackArg, /* argument registered with callback */
- char data /* receive data */
- )
- {
- static BOOL doit = TRUE;
- /*
- * TODO - Device is transferring data, but there is no
- * upstream module connected to receive it. Lets log
- * a message about incoming data being lost. Buts lets
- * do this only once we don‘t want a ‘flood‘ of logged
- * messages.
- */
- if (doit)
- {
- printf ("Dummy rxCallback: 0x%x 0x%x\n",
- (int)callbackArg, (int)data);
- doit = FALSE;
- }
- return;
- }
- /*******************************************************************************
- *
- * dummyErrCallback - dummy Error callback routine
- *
- * There should be an sioLib module to provide dummyCallbacks for all SIO
- * drivers to use.
- *
- * RETURNS: N/A.
- * ARGSUSED
- */
- LOCAL void at91DummyErrCallback
- (
- void * callbackArg, /* argument registered with callback */
- int errorCode, /* error code */
- void * pData, /* ptr to device specific data */
- int size /* size of device specific data */
- )
- {
- static BOOL doit = TRUE;
- /* TODO - We could log the reported error (once). */
- if (doit)
- {
- printf ("Dummy errorCallback: 0x%x 0x%x 0x%x %d\n",
- (int)callbackArg, errorCode, (int)pData, size);
- doit = FALSE;
- }
- return;
- }
- /*******************************************************************************
- *
- * at91Probe - probe for device
- *
- * Try to determine if device is present. Do not reconfigure device if it
- * is there. This should be a passive probe that does not interfere with
- * the device.
- *
- * RETURNS:
- * Returns OK if device adaptor is there, ERROR if not there.
- */
- LOCAL STATUS at91Probe
- (
- AT91_UART_CHAN * pChan /* channel to probe */
- )
- {
- /*
- * the UART and DBGU is internal controller of AT91RM9200 CPU,
- * so we needn‘t to probe it
- */
- return OK;
- }
- #if 0
- /*******************************************************************************
- *
- * at91Verify - verify at91_uart chan structure
- *
- * Given a pointer to what should be a AT91_UART_CHAN, verify that it really
- * is a AT91_UART_CHAN structure.
- *
- * This routine should not be called at every level with every routine. It is
- * primarily provided for use with the xxxDestroy routine. Performance will be
- * a problem if every pointer is checked for validity with every use.
- *
- * RETURNS:
- * Returns OK if pointer is valid, ERROR if not.
- */
- LOCAL STATUS at91Verify
- (
- AT91_UART_CHAN * pChan /* pointer to be verified */
- )
- {
- /*
- * Examine the structure. Look for magic cookies or flag bits.
- * Anything that would confirm this pointer as being a valid
- * AT91_UART_CHAN pointer.
- */
- if (pChan == NULL)
- return ERROR;
- return OK;
- }
- #endif
- #if 0 /* Optional modem control line support */
- /*******************************************************************************
- *
- * at91MstatGet - read device modem control line status
- *
- * Read the device modem control lines and map them to the standard
- * modem signal bits.
- *
- * RETURNS:
- * Returns the modem control line status bits.
- */
- LOCAL int at91MstatGet
- (
- AT91_UART_CHAN *pChan
- )
- {
- AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;
- UINT32 status;
- int result = 0;
- AT91PS_USART pUsart; /* point to UART register index by ioBase of pChan */
- pUsart = (AT91PS_USART)(pChan->ioBase);
- /* Read RX device status */
- status = pUsart->US_CSR;
- /* Now map device status bits, to standard status bits */
- if (rawStatus & TEMPLATE_MSR_CD)
- result |= SIO_MODEM_CD;
- if (rawStatus & TEMPLATE_MSR_DTR)
- result |= SIO_MODEM_DTR;
- if (rawStatus & TEMPLATE_MSR_DSR)
- result |= SIO_MODEM_DSR;
- if (rawStatus & TEMPLATE_MSR_RTS)
- result |= SIO_MODEM_RTS;
- if (rawStatus & TEMPLATE_MSR_CTS)
- result |= SIO_MODEM_CTS;
- return result;
- }
- /*******************************************************************************
- *
- * templateMstatSetClear - set/clear modem control lines
- *
- * This routine allows the user to set or clear individual modem control
- * lines. Of course, only the output lines can actually be changed.
- *
- * RETURNS:
- * OK, or EIO upon detecting a hardware fault.
- */
- LOCAL int templateMstatSetClr
- (
- TEMPLATE_CHAN *pChan,
- UINT bits, /* bits to change */
- BOOL setFlag /* TRUE = set, FALSE = clear */
- )
- {
- UINT8 rawStatus;
- UINT8 rawMask = 0;
- /* Read current modem status */
- TEMPLATE_SIO_READ8 (pChan, TEMPLATE_MSR_ID, &rawStatus);
- /* ignore input only bits */
- bits &= TEMPLATE_OSIG_MASK;
- /* Now map standard bits to device specific bits */
- if (bits & SIO_MODEM_DTR)
- rawMask |= TEMPLATE_MSR_DTR;
- if (bits & SIO_MODEM_RTS)
- rawMask |= TEMPLATE_MSR_RTS;
- /* Update device with new output signals */
- if (setFlag)
- rawStatus |= rawMask; /* set new bits */
- else
- rawStatus &= ~rawMask; /* clear bits */
- TEMPLATE_SIO_WRITE8 (pChan, TEMPLATE_MSR_ID, rawStatus);
- return OK;
- }
- #endif /* optional modem control line support */
时间: 2024-10-10 10:45:22