zoukankan      html  css  js  c++  java
  • at91 uart driver for vxworks


    1. /* at91UART.c - AT91RM9200 serial driver */  
    2.   
    3. /* Copyright 2003-2004 Coordinate Co., Ltd. */  
    4. /* Copyright 1984-2002 Wind River Systems, Inc. */  
    5.   
    6. /* 
    7. modification history 
    8. -------------------- 
    9. 01a,28jul04,cor  created from original at91Sio.c. 
    10. */  
    11.   
    12. /* 
    13. .SH TODO 
    14.  
    15.  - Replace the documentation for this template driver with documentation 
    16. for the driver being written.   
    17.  
    18.  - Begin with an overview of the complete device.  Indicate if the new driver 
    19. only implements a sub-section of the whole device or not. 
    20.  
    21.  - Describe all of the operating modes of the device, and indicate which 
    22. ones this driver implements. 
    23.  
    24.  - Document the device initialization steps to be used in the BSP to create 
    25. and initialize the device.  Document all the macros that 
    26. can be used to customize the driver to a particular hardware environment. 
    27.  
    28.  - Document anything that will help the user to understand how this device 
    29. works and interacts with this driver. 
    30.  
    31. .SH TEMPLATE OVERVIEW 
    32. This is a template serial driver. It can be used as a starting point 
    33. when writing new drivers for VxWorks version 5.4 or later. 
    34.  
    35. These drivers support new functionality not found in the older style 
    36. serial drivers. First, they provide an interface for setting hardware 
    37. options; e.g., the number of stop bits, data bits, parity, etc. 
    38. Second, they provide an interface for polled communication which 
    39. can be used to provided external mode debugging (i.e., ROM monitor 
    40. style debugging) over a serial line. Currently only asynchronous mode 
    41. drivers are supported. 
    42.  
    43. Throughout this file the word "template" is used in place of a real 
    44. device name, which by convention uses the first letter of the 
    45. manufacturers name followed by the part number. For example, the 
    46. Zilog 8530 serial device would have a data structure called a 
    47. Z8530_CHAN, rather than TEMPLATE_CHAN. 
    48.  
    49. .SH CALLBACKS 
    50. Servicing a "transmitter ready" interrupt involves making a callback to a 
    51. higher level library in order to get a character to transmit. 
    52. By default, this driver installs dummy callback routines which do 
    53. nothing. A higher layer library that wants to use this driver (e.g., ttyDrv) 
    54. will install its own callback routines using the SIO_INSTALL_CALLBACK 
    55. ioctl command. (See below). 
    56.  
    57. The prototype for the transmit data callback SIO_CALLBACK_GET_TX_CHAR is: 
    58. .CS 
    59.     int sioTxCharGet 
    60.     ( 
    61.     void * arg,      /@ callback argument @/ 
    62.     char * pChar         /@ ptr to data location @/ 
    63.     ) 
    64. .CE 
    65. This callback routine should fetch the next character to send and store it 
    66. in the location pointed to by pChar.  It returns OK to indicate that a 
    67. character is ready and should be sent.  It returns ERROR to indicate that 
    68. no character was available and the transmitter can be placed in an idle state. 
    69.  
    70. Likewise, a receiver interrupt handler makes a callback to pass the 
    71. character to the higher layer library.  It will be called by the driver 
    72. for each character received.  This routine should capture the data and pass 
    73. it along to other layers and eventually to the user. 
    74.  
    75. The prototype for the receive data callback SIO_CALLBACK_PUT_RCV_CHAR is: 
    76. .CS 
    77.     void sioRxCharPut 
    78.     ( 
    79.     void * arg,      /@ callback argument @/ 
    80.     char data        /@ data byte @/ 
    81.     ) 
    82. .CE 
    83. A new error handling callback has been added SIO_CALLBACK_ERROR. This driver 
    84. should use this callback to inform the higher layer about error conditions. 
    85. The prototype for this callback is: 
    86. .CS 
    87.     void sioErrorRtn 
    88.     ( 
    89.     void * arg,      /@ callback argument @/ 
    90.     int code,        /@ error code @/ 
    91.     void * pData,        /@ opt dev specific data @/ 
    92.     int dataSize         /@ opt size of data in bytes @/ 
    93.     ) 
    94. .CE 
    95. The available error codes for this callback are: 
    96. .CS 
    97.     SIO_ERROR_FRAMING    /@ (1) Framing error @/ 
    98.     SIO_ERROR_PARITY     /@ (2) Parity error @/ 
    99.     SIO_ERROR_OFLOW  /@ (3) data overflow @/ 
    100.     SIO_ERROR_UFLOW  /@ (4) data underflow @/ 
    101.     SIO_ERROR_CONNECT    /@ (5) connection made @/ 
    102.     SIO_ERROR_DISCONNECT /@ (6) connection lost @/ 
    103.     SIO_ERROR_NO_CLK     /@ (7) clock lost @/ 
    104.     SIO_ERROR_UNKNWN     /@ (8) other errors @/ 
    105. .CE 
    106. For engineering purposes, the driver may return device specific data in 
    107. the form of a data buffer. The argument pData is the location of the buffer 
    108. and dataSize is its size, in bytes.  The data is not guaranteed to be static 
    109. so it should be copied to a static buffer for safekeeping. 
    110.  
    111. .SH MODES 
    112. Ideally the driver should support both polled and interrupt modes, and be 
    113. capable of switching modes dynamically. However this is not required. 
    114. VxWorks will be able to support a tty device on this driver even if 
    115. the driver only supports interrupt mode. 
    116. Polled mode is provided solely for WDB system mode usage.  Users can use 
    117. the polled mode interface directly, but there is no clear reason for doing so. 
    118. Normal access to SIO devices through ttyDrv only uses interrupt mode. 
    119.  
    120. For dynamically switchable drivers, be aware that the driver may be 
    121. asked to switch modes in the middle of its input ISR. A driver's input ISR 
    122. will look something like this: 
    123.  
    124.    inChar = *pDev->dr;          /@ read a char from data register @/ 
    125.    *pDev->cr = GOT_IT;          /@ acknowledge the interrupt @/ 
    126.    pDev->putRcvChar (...);      /@ give the character to the higher layer @/ 
    127.  
    128. If this channel is used as a communication path to an external mode 
    129. debug agent, and if the character received is a special "end of packet" 
    130. character, then the agent's callback will lock interrupts, switch 
    131. the device to polled mode, and use the device in polled mode for awhile. 
    132. Later on the agent will unlock interrupts, switch the device back to 
    133. interrupt mode, and return to the ISR. 
    134. In particular, the callback can cause two mode switches, first to polled mode 
    135. and then back to interrupt mode, before it returns. 
    136. This may require careful ordering of the callback within the interrupt 
    137. handler. For example, you may need to acknowledge the interrupt before 
    138. invoking the callback. 
    139.  
    140. .SH USAGE 
    141. The driver is typically called only by the BSP. The directly callable 
    142. routines in this module are templateSioCreate(), templateSioDestroy(). 
    143.  
    144. .SH BSP 
    145. By convention all the BSP-specific serial initialization is performed in 
    146. a file called sysSerial.c, which is #include'ed by sysLib.c. 
    147.  
    148. This driver can be customized by redefining the macros SYS_SIO_READ8 and 
    149. SYS_SIO_WRITE8.  These two macros are used for all accesses to the 
    150. actual chip.  If not defined, the source code will assume a simple memory 
    151. mapped device using byte read/write access to all registers. 
    152.  
    153. The macros SYS_SIO_INT_CONNECT, SYS_SIO_INT_DISCONNECT, SYS_SIO_INT_ENABLE, 
    154. and SYS_SIO_PROBE can be redefined by the BSP to perform basic low level 
    155. routines with the same calling sequence as intConnect(), intConnect(), 
    156. intEnable(), and vxMemProbe(). 
    157.  
    158. .SH TESTING 
    159. The interrupt driven interface can be tested in the usual way; VxWorks 
    160. prints to the serial console when it comes up, so seeing the usual VxWorks 
    161. output on power-up shows that the driver is basically working. 
    162. The VxWorks portkit test can be used to perform a more strenuous test. 
    163.  
    164. The polled interface should be easy enough to verify - you should be able 
    165. to call the channels SIO_MODE_SET ioctl to put it in polled mode.  Note 
    166. that the usual print tools won't work with a serial channel in polled mode. 
    167. Some agent has to perform a polling loop to handle input/output on a 
    168. character by character basis.  It is not automatic.  The WDB agent 
    169. performs its own polling loop when it switches the WDB serial line into 
    170. polled mode.  
    171.  
    172. The dynamic mode switching can be verified using the tornado tools. 
    173. Reconfigure the agent to use the WDB_COMM_UDLP_SLIP communication path (see 
    174. the Configuration section in the VxWorks run-time Guide for details). 
    175. Start VxWorks, and connect the tgtsvr to the agent using the wdbserial 
    176. backend (see the Tornado Users Guide for details). 
    177. Start the wtxtcl shell as follows: 
    178.     % wtxtcl 
    179. From the tcl prompt, attach to the target server: 
    180.     wtxtcl.ex> wtxToolAttach <tgtsvr name> 
    181. Tell the agent to switch to external mode, and verify the reply is OK (0). 
    182.     wtxtcl.ex>wtxAgentModeSet 2 
    183.     0 
    184. Ask the agent to suspend the system (the request will reach the agent in 
    185. interrupt mode, but the reply will be sent in polled mode): 
    186.     wtxtcl.ex>wtxContextSuspend 0 0 
    187.     0 
    188. At this point the target will be suspended. The console should apprear 
    189. frozen (if the board has a console device), and you will not be able to 
    190. "ping" the target's network interface. 
    191. Resume the target: 
    192.     wtxtcl.ex>wtxContextResume 0 0 
    193.     0 
    194. The target should now be running again, so you should be able to type into 
    195. the console (if the board has a console device) and ping the targets network 
    196. interface from the host. 
    197.  
    198. .SH INCLUDE FILES: 
    199. at91Sio.h sioLib.h 
    200. */  
    201.   
    202. #include "vxWorks.h"  
    203. #include "intLib.h"  
    204. #include "errnoLib.h"  
    205. #include "iosLib.h"     /* For S_iosLib_DEVICE_NOT_FOUND */  
    206. #include "cacheLib.h"  
    207. #include "stdlib.h" /* malloc/free */  
    208. #include "stdio.h"  /* for printf */  
    209. #include "vxLib.h"  /* for vxMemProbe */  
    210. #include "at91.h"  
    211. #include "at91rm9200.h"  
    212. #include "at91If.h"  
    213. #include "at91Sio.h"  
    214. #include "archarmivarm.h"  
    215.   
    216. #define DEFAULT_BAUD    9600  
    217.   
    218.   
    219. /* channel control register (write) definitions */  
    220.   
    221. #if 0  
    222.   
    223. /* TODO - These are just made up bit defines for a mythical device! */  
    224.   
    225. #define TEMPLATE_RESET_CHIP 0x07    /* reset all */  
    226. #define TEMPLATE_RESET_TX   0x01    /* reset the transmitter */  
    227. #define TEMPLATE_RESET_ERR  0x02    /* reset error condition */  
    228. #define TEMPLATE_RESET_INT  0x04    /* acknoledge the interrupt */  
    229. #define TEMPLATE_INT_ENABLE 0x08    /* enable interrupts */  
    230. #define TEMPLATE_TX_ENABLE  0x10    /* enable interrupts */  
    231. #define TEMPLATE_RX_ENABLE  0x20    /* enable interrupts */  
    232.   
    233. /* channel status register (read) definitions */  
    234.   
    235. #define TEMPLATE_CR_OKAY    0x00    /* no error conditions */  
    236. #define TEMPLATE_CR_TX_READY    0x01    /* txmitter ready for another char */  
    237. #define TEMPLATE_CR_TX_ERROR    0x04    /* txmitter int enable */  
    238. #define TEMPLATE_CR_RX_AVAIL    0x10    /* character has arrived */  
    239. #define TEMPLATE_CR_RX_ERROR    0x40    /* receiver error */  
    240.   
    241. /* channel modem status register definitions */  
    242.   
    243. #define TEMPLATE_MSR_RTS    0x1 /* RTS signal asserted */  
    244. #define TEMPLATE_MSR_DTR    0x2 /* DTR signal asserted */  
    245. #define TEMPLATE_MSR_DSR    0x4 /* DSR signal asserted */  
    246. #define TEMPLATE_MSR_CTS    0x8 /* CTS signal asserted */  
    247. #define TEMPLATE_MSR_CD     0x10    /* CD signal asserted */  
    248.   
    249. /* input and output signals */  
    250.   
    251. #define TEMPLATE_ISIG_MASK  (SIO_MODEM_CTS|SIO_MODEM_DSR|SIO_MODEM_CD)  
    252. #define TEMPLATE_OSIG_MASK  (SIO_MODEM_RTS|SIO_MODEM_DTR)  
    253.   
    254. /* channel modem control register definitions */  
    255.   
    256. #define TEMPLATE_MC_RTS     0x1 /* enable RTS */  
    257. #define TEMPLATE_MC_DTR     0x2 /* enable DTR */  
    258.   
    259. #endif  
    260.   
    261. #define AT91_BAUD_MIN   110  
    262. #define AT91_BAUD_MAX   921600  
    263.   
    264.   
    265. /* Hardware abstraction macros */  
    266.   
    267. #if 0  
    268. /* Macros from BSP */  
    269.   
    270. #define SYS_SIO_READ8(addr, pData)   
    271.     (*pData = *(UINT8 *)(addr))  
    272. #define SYS_SIO_WRITE8(addr, data)   
    273.     (*(UINT8 *)addr = data)  
    274. #define SYS_SIO_INT_CONNECT(vec, rtn, arg)   
    275.     intConnect ((VOIDFUNCPTR *)vec, (VOIDFUNCPTR)rtn, (int)arg)  
    276. #define SYS_SIO_INT_DISCONNECT(vec, rtn, arg)   
    277.     intConnect ((VOIDFUNCPTR *)vec, NULL, 0)  
    278. #define SYS_SIO_INT_ENABLE(level)   
    279.     intEnable (level)  
    280. #define SYS_SIO_PROBE(addr, mode, size, pData)   
    281.     vxMemProbe (addr, mode, size, pData)  
    282. /* #define CACHE_PIPE_FLUSH() */  
    283.   
    284.   
    285. /* Local driver abstractions, following bus/adaptor model */  
    286.   
    287. #define TEMPLATE_SIO_READ8(pChan, reg, result)   
    288.     SYS_SIO_READ8(((pChan->ioBase) + reg),result)  
    289.   
    290. #define TEMPLATE_SIO_WRITE8(pChan, reg, data)   
    291.     SYS_SIO_WRITE8(((pChan->ioBase) + reg),data)  
    292.   
    293. #define TEMPLATE_SIO_INT_CONNECT(pChan, vec, rtn, arg)   
    294.     do {   
    295.     SYS_SIO_INT_CONNECT((pChan->vecBase) + vec, rtn, arg);   
    296.     SYS_SIO_INT_ENABLE(pChan->intLevel);   
    297.     } while (0)  
    298.   
    299. #define TEMPLATE_INT_DISCONNECT(pChan, vec, rtn, arg)   
    300.     SYS_SIO_INT_DISCONNECT(((pChan)->vecBase + vec), rtn, arg)  
    301.     /* Do NOT disable interrupt level for disconnect */  
    302.   
    303. #define TEMPLATE_PROBE(pChan, offset, dir, size, ptr)   
    304.     SYS_SIO_PROBE((char *)((pChan)->ioBase + offset), dir, size, ptr)  
    305.   
    306. #define TEMPLATE_PIPE_FLUSH(pChan)   
    307.     CACHE_PIPE_FLUSH()  
    308.   
    309. #endif   
    310.   
    311. /* forward static declarations */  
    312.   
    313.   
    314. LOCAL int   at91TxStartup (SIO_CHAN * pSioChan);  
    315. LOCAL int   at91CallbackInstall (SIO_CHAN *pSioChan, int callbackType,  
    316.             STATUS (*callback)(void *,...), void *callbackArg);  
    317. LOCAL int   at91PollOutput (SIO_CHAN *pSioChan, char    outChar);  
    318. LOCAL int   at91PollInput (SIO_CHAN *pSioChan, char *thisChar);  
    319. LOCAL int   at91Ioctl (SIO_CHAN *pSioChan, int request, void *arg);  
    320. LOCAL STATUS    at91DummyTxCallback (void *, char *);  
    321. LOCAL void  at91DummyRxCallback (void *, char);  
    322. LOCAL void  at91DummyErrCallback (void *, int, void *, int);  
    323. LOCAL void  at91UARTIntRx (AT91_UART_CHAN * pChan);  
    324. LOCAL void  at91UARTIntTx (AT91_UART_CHAN * pChan);  
    325. LOCAL STATUS    at91Probe (AT91_UART_CHAN * pChan);  
    326. /*  
    327. LOCAL STATUS    at91Verify (AT91_UART_CHAN *pChan); 
    328. LOCAL int   at91MstatGet (AT91_UART_CHAN *pChan); 
    329. LOCAL int   at91MstatSetClr (AT91_UART_CHAN *pChan, UINT bits, BOOL setFlag); 
    330. */  
    331. /* local variables */  
    332.   
    333. LOCAL   SIO_DRV_FUNCS at91UARTDrvFuncs =  
    334.     {  
    335.     at91Ioctl,  
    336.     at91TxStartup,  
    337.     at91CallbackInstall,  
    338.     at91PollInput,  
    339.     at91PollOutput  
    340.     };  
    341.   
    342. /****************************************************************************** 
    343. * at91UARTDevInit - initialise an AT91_SIO channel 
    344. * This routine initialises some SIO_CHAN function pointers and then resets 
    345. * the chip to a quiescent state.  Before this routine is called, the BSP 
    346. * must already have initialised all the device addresses, etc. in the 
    347. * AT91_UART_CHAN structure. 
    348. * RETURNS: N/A 
    349. */  
    350.   
    351. void at91UARTDevInit  
    352.     (  
    353.     AT91_UART_CHAN * pChan  /* ptr to AT91_UART_CHAN describing this channel */  
    354.     )  
    355.     {  
    356.     AT91PS_USART pUsart;    /* point to UART register index by ioBase of pChan */  
    357.     AT91PS_PIO pPIOA, pPIOB;    /* point to  PIO Controller A, B */  
    358.     AT91_UART_PARAS *pParas;  
    359.   
    360.     int oldIntLvl;  
    361.   
    362.     if (pChan != NULL)  
    363.     {  
    364.     pChan->sio.pDrvFuncs = &at91UARTDrvFuncs;  
    365.   
    366.     /* install dummy driver callbacks */  
    367.   
    368.     pChan->getTxChar    = at91DummyTxCallback;  
    369.     pChan->putRcvChar   = at91DummyRxCallback;  
    370.     pChan->errorRtn      = at91DummyErrCallback;  
    371.   
    372.     pChan->intConnect    = FALSE;    /* int's not connected yet */  
    373.   
    374.     /* setting polled mode is one way to make the device quiet */  
    375.     pChan->mode = SIO_MODE_POLL; /* setting mode to poll mode */  
    376.       
    377.     if (at91Probe (pChan) == OK)  
    378.         {  
    379.         oldIntLvl = intLock();  
    380.           
    381.         pParas = pChan->pUart;  
    382.         pChan->ioBase = pParas->ioBase;   /* set parameter of pParas to pChan for easy usage */  
    383.         pUsart = (AT91PS_USART)(pParas->ioBase);  
    384.         pPIOA = (AT91PS_PIO)(AT91RM9200_PIOA_BASE_ADDR);  
    385.         pPIOB = (AT91PS_PIO)(AT91RM9200_PIOB_BASE_ADDR);  
    386.   
    387.         *(volatile unsigned int *)AT91RM9200_PMC_PCER = 1 << pParas->uartId;   /* enable clock */  
    388.         pPIOA->PIO_ASR = pParas->PIOA_ASR;  
    389.         pPIOA->PIO_BSR = pParas->PIOA_BSR;  
    390.         pPIOA->PIO_PDR = pParas->PIOA_ASR | pParas->PIOA_BSR;  
    391.         pPIOB->PIO_ASR = pParas->PIOA_ASR;  
    392.         pPIOB->PIO_BSR = pParas->PIOA_BSR;   
    393.         pPIOB->PIO_PDR = pParas->PIOB_ASR | pParas->PIOB_BSR;  
    394.   
    395.         pUsart->US_IDR = -1; /* disable all USART interrupts */  
    396.         /* reset & disble transmit and receive */  
    397.         pUsart->US_CR = AT91RM9200_US_CR_RSTRX | AT91RM9200_US_CR_RSTTX |   
    398.                         AT91RM9200_US_CR_RXDIS | AT91RM9200_US_CR_TXDIS;      
    399.         pUsart->US_BRGR = AT91_MASTER_CLOCK / (pParas->baudRate) / 16;    /* 115200 baud with 18.432 Mhz Crystal */  
    400.   
    401.         pUsart->US_RTOR = AT91_USART_RX_TIMEOUT; /* Receiver Time-out Register */  
    402.         pUsart->US_TTGR = 0; /* Transmitter timeguart is disabled */      
    403.         pUsart->US_FIDI = 0; /* in ISO7816 mode, BRG generates no signal */  
    404.   
    405.         /* Disable PDC Channels for DBGU and Initial the State of it */  
    406.         pUsart->US_PTCR = AT91RM9200_PDC_PTCR_TXTDIS | AT91RM9200_PDC_PTCR_RXTDIS;  
    407.   
    408.         pUsart->US_TNPR = 0;  
    409.         pUsart->US_TNCR = 0; /* clear out next transmit counts */  
    410.           
    411.         pUsart->US_RNPR = 0;  
    412.         pUsart->US_RNCR = 0; /* clear out next receive counts */  
    413.           
    414.         pUsart->US_TPR = 0;  
    415.         pUsart->US_TCR = 0;  /* clear out transmit counts */  
    416.   
    417.         pUsart->US_RPR = 0;  
    418.         pUsart->US_RCR = 0;  /* clear out receive counts */  
    419.   
    420.         pUsart->US_MR = pParas->uartOption;   /* default mode */  
    421.               
    422.         intUnlock(oldIntLvl);  
    423.   
    424.         pChan->mode = SIO_MODE_INT;  
    425.   
    426.         /* Enable transmit and received of UART Device */  
    427.         pUsart->US_CR = AT91RM9200_US_CR_RXEN | AT91RM9200_US_CR_TXEN;  
    428.           
    429.         }  
    430.     else  
    431.         {  
    432.         /* Whoops, device is not there! */  
    433.   
    434.         free ((char *)pChan);  
    435.         errnoSet (S_iosLib_DEVICE_NOT_FOUND);  
    436.           
    437.         return;  
    438.         }  
    439.     }  
    440.   
    441.     return;  
    442.     }  
    443.   
    444. /******************************************************************************* 
    445. * at91UARTInt - handle an AT91RM9200 UART interrupt 
    446. * This routine is called to handle AT91RM9200 UART interrupts. 
    447. */  
    448.   
    449. void at91UARTInt  
    450.     (  
    451.     AT91_UART_CHAN *pChan  
    452.     )  
    453.     {  
    454.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */      
    455.     UINT32  status;  
    456.     int errorCode = SIO_ERROR_NONE;  
    457.   
    458.     status = pUsart->US_CSR;  
    459.   
    460.     if (status)  
    461.     {  
    462.         /* we can make below process several times when TXRDY or RXRDY is there */  
    463.           
    464.         if (status & (AT91RM9200_US_SR_RXRDY))  
    465.             at91UARTIntRx (pChan);  
    466.   
    467.         /* Check for error conditions */  
    468.   
    469.         if (status & (AT91RM9200_US_SR_PARE | AT91RM9200_US_SR_FRAME | AT91RM9200_US_SR_OVRE))  
    470.         {  
    471.         /* 
    472.          * Determine precise error condition and perform 
    473.          * recovery actions. 
    474.          */  
    475.             pUsart->US_CR = AT91RM9200_US_CR_RSTSTA;  
    476.               
    477.   
    478.             /* 
    479.              * If needed, you should acknowledge or reset the interrupt source 
    480.              * as soon as possible, usually before passing any error conditions 
    481.              * upstream. 
    482.              */  
    483.             if (status & (AT91RM9200_US_SR_PARE))  
    484.                 {  
    485.                     errorCode = SIO_ERROR_PARITY;  
    486.                 }  
    487.             else if (status & (AT91RM9200_US_SR_FRAME))  
    488.                 {  
    489.                     errorCode = SIO_ERROR_FRAMING;  
    490.                 }  
    491.               
    492.             if (errorCode != SIO_ERROR_NONE)  
    493.             (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);  
    494.   
    495.             if (status & (AT91RM9200_US_SR_OVRE))  
    496.                 {  
    497.                     errorCode = SIO_ERROR_OFLOW;  
    498.                 (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);  
    499.                 }  
    500.         }  
    501.   
    502.         if (status & (AT91RM9200_US_SR_TXRDY))  
    503.             at91UARTIntTx (pChan);  
    504.     }  
    505.   
    506.     }  
    507.   
    508. /****************************************************************************** 
    509. * at91UARTIntRx - handle a channel's receive-character interrupt 
    510. * RETURNS: N/A 
    511. */   
    512.   
    513. LOCAL void at91UARTIntRx  
    514.     (  
    515.     AT91_UART_CHAN *    pChan       /* channel generating the interrupt */  
    516.     )  
    517.     {  
    518.     char   inChar;  /* receive data */  
    519.     UINT32 rxStatus = 0; /* receive status */  
    520. /*     
    521.     STATUS status = OK; 
    522.     int errorCode = SIO_ERROR_NONE; 
    523. */  
    524.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */      
    525.   
    526.     /* 
    527.      * 
    528.      * Get status and data from the device. Determine if valid data is ready 
    529.      * or not. 
    530.      * 
    531.      * For PCI devices, do an immediate return if device is not asserting 
    532.      * an interrupt. 
    533.      */  
    534.   
    535.     rxStatus = pUsart->US_CSR;  
    536.       
    537.     while (rxStatus & AT91RM9200_US_SR_RXRDY)  
    538.         {  
    539.         inChar = pUsart->US_RHR;  
    540.         /* RXRDY bit in US_CSR will be clear when RHR is read */  
    541.           
    542.         /* send data character upstream */  
    543.         (*pChan->putRcvChar) (pChan->putRcvArg, inChar);  
    544.   
    545.         if (pChan->mode != SIO_MODE_INT) break;  
    546.   
    547.         rxStatus = pUsart->US_CSR;  
    548.         }  
    549. #if 0   /* will be processed in at91UARTIntErr */  
    550.     if (status == ERROR)  
    551.     {  
    552.     /* send error notification upstream */  
    553.   
    554.     (*pChan->errorRtn) (pChan->errorArg, SIO_ERROR_UNKNWN, NULL, 0);  
    555.     }  
    556. #endif   
    557. #if 0 /* Keyboard emulation code */  
    558.   
    559.     /* 
    560.      * TODO - For a keyboard type device we would map the raw scan code 
    561.      * to ASCII, or other mapping.  Do that here. 
    562.      */  
    563.   
    564.     if (pChan->scanMode == SIO_KYBD_MODE_ASCII)  
    565.         inChar = templateAsciiTbl[(UINT8)inChar];  
    566. #endif  
    567.   
    568.     }  
    569.   
    570. /****************************************************************************** 
    571. * at91UARTIntTx - handle a channels transmitter-ready interrupt 
    572. * RETURNS: N/A 
    573. */   
    574.   
    575. LOCAL void at91UARTIntTx  
    576.     (  
    577.     AT91_UART_CHAN *pChan       /* channel generating the interrupt */  
    578.     )  
    579.     {  
    580.     char    outChar;  
    581.     UINT32 txStatus;    /* status of transmit */  
    582.     /* BOOL txReady = TRUE; */  
    583.     int     errorCode = SIO_ERROR_NONE;  
    584.   
    585.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase);;    /* point to UART register index by ioBase of pChan */          
    586.   
    587.     /* 
    588.      * Check the Tx status 
    589.      * 
    590.      * For PCI devices, do an immediate return if device is not asserting 
    591.      * an interrupt. 
    592.      */  
    593.   
    594. #if 0  
    595.   
    596.     /* Check for error conditions */  
    597.       
    598.     if (crData & TEMPLATE_CR_TX_ERROR)  
    599.     {  
    600.     /* 
    601.      * TODO - Typically you should determine the precise error condition 
    602.      * and perform all recovery operations here. 
    603.      */  
    604.   
    605.     TEMPLATE_SIO_WRITE8 (pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_TX);  
    606.   
    607.     errorCode = SIO_ERROR_UNKNWN;  
    608.   
    609.     txReady = TRUE; /* set to false if xmitter is not ready now */  
    610.     }  
    611.       
    612. #endif  
    613.     /* 
    614.      * If transmitter is okay and ready to send, lets see if there is a 
    615.      * data character ready to be sent. 
    616.      * 
    617.      * If there's a character to transmit then write it out, else reset (idle) 
    618.      * the transmitter. For chips with output FIFO's it is more efficient 
    619.      * to fill the entire FIFO here. 
    620.      */  
    621.     txStatus = pUsart->US_CSR;  
    622.   
    623.     if (txStatus & AT91RM9200_US_SR_TXRDY)  
    624.     {  
    625.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)  
    626.         {  
    627.         /* Output data to device.  */  
    628.   
    629.         pUsart->US_THR = outChar;  
    630.         /* need to insert a wait time for transmit finished ? */  
    631.             txStatus = pUsart->US_CSR;  
    632.   
    633.         /* 
    634.          * If a device error occurs at this point, then 
    635.          * isolate the precise error type and try to recover. 
    636.          */  
    637.         }  
    638.     else  
    639.         {  
    640.         /* 
    641.          * There is no more data to send. 
    642.          * 
    643.          * Put XMTR in an idle state. Higher layer 
    644.          * will call TxStartup entry to resume xmit operations. 
    645.          */  
    646.   
    647.         pUsart->US_IDR = AT91RM9200_US_INT_TXRDY;      
    648.            /* 
    649.            pUsart->US_CR = AT91RM9200_US_CR_TXDIS | AT91RM9200_US_CR_RSTTX; */ /* disable transmit */  
    650.              
    651.            /* break; */  
    652.         }  
    653.     }  
    654.   
    655.     /* 
    656.      * If needed, you should acknowledge or reset the interrupt source 
    657.      * as soon as possible, usually before passing any error conditions 
    658.      * upstream. 
    659.      */  
    660.   
    661.     /* US_TXRDY will be cleared when char is sent */  
    662.   
    663.     /* Pass any errorCodes upstream.  */  
    664.   
    665.     if (errorCode != SIO_ERROR_NONE)  
    666.     {  
    667.     (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);  
    668.     }  
    669.     }  
    670.   
    671. #if 0  
    672.   
    673. /****************************************************************************** 
    674. * at91UARTIntErr - handle a channels error interrupt 
    675. * RETURNS: N/A 
    676. */   
    677.   
    678. LOCAL void at91UARTIntErr  
    679.     (  
    680.     AT91_UART_CHAN *    pChan       /* channel generating the interrupt */  
    681.     )  
    682.     {  
    683.   
    684.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase);;    /* point to UART register index by ioBase of pChan */          
    685.       
    686.     UINT32 errStatus;  
    687.   
    688.     errStatus = pUsart->US_CSR;  
    689.       
    690.     /* 
    691.      * Determine the precise error condition and perform recovery 
    692.      * operations. 
    693.      * 
    694.      * For PCI devices, do an immediate return if device is not asserting 
    695.      * an interrupt. 
    696.      */  
    697.   
    698.     if (errStatus & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE)  
    699.     {  
    700.   
    701.   
    702.     }  
    703. }  
    704. #endif   
    705.   
    706. /****************************************************************************** 
    707. * templateTxStartup - start the interrupt transmitter 
    708. * This routine exits to inform the device to start transmitting data again. 
    709. * The actual data will be obtained by calling the TxCharGet callback routine. 
    710. * This routine is usually just the same as the tx interrupt routine.  This 
    711. * routine runs at task level context and does not have to be interrupt safe. 
    712. * RETURNS: OK on success, ENOSYS if the device is polled-only, or 
    713. * EIO on hardware error. 
    714. */  
    715.   
    716. LOCAL int at91TxStartup  
    717.     (  
    718.     SIO_CHAN * pSioChan                 /* channel to start */  
    719.     )  
    720.     {  
    721.     AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;  
    722.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */  
    723.       
    724.     /* char outChar; */  
    725.   
    726.     /* This routine should only be called while in interrupt mode */  
    727.     /* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE 
    728.        NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE 
    729.        NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE 
    730.        NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE 
    731.      */  
    732.     /* pChan->mode = SIO_MODE_POLL; */  
    733.   
    734.     if (pChan->mode == SIO_MODE_INT)  
    735.         {  
    736. #if 0  
    737.         if (pChan->options & CLOCAL)  
    738.             {  
    739.             /* No modem control - start immediately */  
    740.             }  
    741.         else  
    742.             {  
    743.         /* 
    744.          * Modem controls are active.  
    745.          * 
    746.          * If CTS is high, we can start immediately so just enable 
    747.          * the TX interrupt. 
    748.          * 
    749.          * If CTS is low, then we cannot send now.  The driver 
    750.          * should be set up to generate a TX interrupt when the CTS 
    751.          * line returns to the active state. 
    752.          */  
    753.             }  
    754.   
    755.         /* 
    756.      * Enable the correct interrupts. A TX interrupt should either 
    757.      * occur immediately, or later when CTS becomes active.  That will start 
    758.      * the flow of data. 
    759.      * 
    760.      * There are two usual methods here.  The first is to just enable 
    761.      * TX interrupts, which should cause an immediate TX interrupt, which 
    762.      * will begin fetching and sending characters. 
    763.      * 
    764.      * The second method is to call the getTxChara callback here, put 
    765.      * the data to the transmitter directly, and then to enable TX 
    766.      * interrupts to fetch and send additional characters. 
    767.      */  
    768. #endif   
    769. #if 0  
    770.     if ((pUsart->US_CSR & AT91C_US_TXRDY) &&   
    771.         ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR))  
    772.         {  
    773.         /* Output data to device.  */  
    774.   
    775.         pUsart->US_THR = outChar;  
    776.   
    777.         /* 
    778.          * If a device error occurs at this point, then 
    779.          * isolate the precise error type and try to recover. 
    780.          */  
    781.         }  
    782. #endif  
    783.   
    784.      /* intEnable(pChan->intLevel); */  
    785.      /* pUsart->US_CR = AT91C_US_TXEN; */  
    786.      pUsart->US_IER = AT91RM9200_US_INT_TXRDY;   /* we need set it again here ? */  
    787.      return OK;  
    788.         }  
    789.     else  
    790. /*      
    791.     while ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR) 
    792.     { 
    793.         while (EAGAIN == at91PollOutput ((SIO_CHAN *)pChan, outChar)); 
    794.     } 
    795. */      
    796.     return ENOSYS;      /* Not valid for polled mode operation */  
    797.   
    798.     return (OK);  
    799.     }  
    800.   
    801.   
    802.   
    803. /****************************************************************************** 
    804. * at91CallbackInstall - install ISR callbacks to get/put chars 
    805. * This driver allows interrupt callbacks for transmitting characters 
    806. * and receiving characters. In general, drivers may support other 
    807. * types of callbacks too. 
    808. * RETURNS: OK on success, or ENOSYS for an unsupported callback type. 
    809. */   
    810.   
    811. LOCAL int at91CallbackInstall  
    812.     (  
    813.     SIO_CHAN *  pSioChan,               /* channel */  
    814.     int     callbackType,           /* type of callback */  
    815.     STATUS  (*callback)(void *,...),  /* callback */  
    816.     void *      callbackArg             /* parameter to callback */  
    817.     )  
    818.     {  
    819.     AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;  
    820.   
    821.     switch (callbackType)  
    822.     {  
    823.     case SIO_CALLBACK_GET_TX_CHAR:  
    824.         pChan->getTxChar = (STATUS (*)(void *, char *))callback;  
    825.         pChan->getTxArg  = callbackArg;  
    826.         return (OK);  
    827.   
    828.     case SIO_CALLBACK_PUT_RCV_CHAR:  
    829.         pChan->putRcvChar    = (void (*)(void *, char))callback;  
    830.         pChan->putRcvArg = callbackArg;  
    831.         return (OK);  
    832.   
    833.     case SIO_CALLBACK_ERROR:  
    834.         pChan->errorRtn  = (void (*)(void *, int, void *, int))callback;  
    835.         pChan->errorArg  = callbackArg;  
    836.         return (OK);  
    837.   
    838.     default:  
    839.         return (ENOSYS);  
    840.     }  
    841.     }  
    842.   
    843. /******************************************************************************* 
    844. * templatePollOutput - output a character in polled mode 
    845. * Polled mode operation takes place without any kernel or other OS 
    846. * services available.  Use extreme care to insure that this code does not 
    847. * call any kernel services.  Polled mode is only for WDB system mode use. 
    848. * Kernel services, semaphores, tasks, etc, are not available during WDB 
    849. * system mode. 
    850. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN 
    851. * if the output buffer if full. ENOSYS if the device is 
    852. * interrupt-only. 
    853. */  
    854.   
    855. LOCAL int at91PollOutput  
    856.     (  
    857.     SIO_CHAN *  pSioChan,  
    858.     char    outChar  
    859.     )  
    860.     {  
    861.     AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;  
    862.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */  
    863.       
    864.     UINT32  status;  
    865.   
    866.     /* is the transmitter ready to accept a character? */  
    867.   
    868.     /* Read TX device status */  
    869.   
    870.     status = pUsart->US_CSR;  
    871.   
    872.     /* determine if transmitter is ready */  
    873.   
    874.     if (0x00 == (status & (AT91RM9200_US_SR_TXRDY)))  
    875.     /* device is busy, try again later */  
    876.         return (EAGAIN);  
    877.       
    878.     /*  transmit the character */  
    879.     pUsart->US_THR = (AT91_REG)outChar;  
    880.   
    881.     return (OK);  
    882.     }  
    883.   
    884. /****************************************************************************** 
    885. * at91PollInput - poll the device for input 
    886. * Polled mode operation takes place without any kernel or other OS 
    887. * services available.  Use extreme care to insure that this code does not 
    888. * call any kernel services.  Polled mode is only for WDB system mode use. 
    889. * Kernel services, semaphores, tasks, etc, are not available during WDB 
    890. * system mode. 
    891. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN 
    892. * if the input buffer if empty, ENOSYS if the device is 
    893. * interrupt-only. 
    894. */  
    895.   
    896. LOCAL int at91PollInput  
    897.     (  
    898.     SIO_CHAN *  pSioChan,  
    899.     char *  thisChar  
    900.     )  
    901.     {  
    902.     AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;  
    903.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */  
    904.       
    905.     UINT32  status;  
    906.   
    907.     /* Read RX device status */  
    908.   
    909.     status = pUsart->US_CSR;  
    910.   
    911.     /* Check if receive data is available */  
    912.   
    913.     if (0x00 == (status & (AT91RM9200_US_SR_RXRDY)))  
    914.     {  
    915.     return EAGAIN;  /* no input available at this time */  
    916.     }  
    917.   
    918.     /* Check for receive error conditions */  
    919.   
    920.     if (0x00 != (status & (AT91RM9200_US_SR_PARE | AT91RM9200_US_SR_FRAME | AT91RM9200_US_SR_OVRE)))  
    921.     {  
    922.     /* Decode and handle the specific error condition */  
    923.   
    924.     pUsart->US_CR = AT91RM9200_US_CR_RSTSTA; /* reset receive of USART to clear error */  
    925.   
    926.     /* Do NOT call the error callback routine, just return EIO */  
    927.   
    928.     return EIO;  
    929.     }  
    930.   
    931.         /* read character, store it, and return OK  */  
    932.   
    933.     *thisChar = (char)(pUsart->US_RHR);  
    934.   
    935.        return (OK);  
    936.     }  
    937.   
    938. /****************************************************************************** 
    939. * at91ModeSet - toggle between interrupt and polled mode 
    940. * RETURNS: OK on success, EIO on unsupported mode. 
    941. */  
    942.   
    943. LOCAL int at91ModeSet  
    944.     (  
    945.     AT91_UART_CHAN * pChan,     /* channel */  
    946.     uint_t      newMode             /* new mode */  
    947.     )  
    948.     {  
    949.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */  
    950.     AT91_UART_PARAS *pParas =  (AT91_UART_PARAS *)(pChan->pUart);  
    951.      
    952.     int oldIntLvl;  
    953.       
    954.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))  
    955.     return (EIO);  
    956.   
    957.     oldIntLvl = intLock();  
    958.       
    959.     /*   
    960.      * use this function will made all the action done in  
    961.      * at91IosDevInit be cancelled, so we can't do it now 
    962.     pUsart->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; 
    963.     */  
    964.     if (pChan->mode == SIO_MODE_INT)  
    965.     {  
    966.     /* switch device to interrupt mode */  
    967.   
    968.     if (pChan->intConnect == FALSE)  
    969.         {  
    970.         /* interconnect ISR to intvector */;  
    971.         intConnect (INUM_TO_IVEC(pParas->vector), at91UARTInt, (int)pChan);  
    972.         pChan->intConnect = TRUE;  
    973.         }  
    974.     /* enable interrupt of device */  
    975.     pUsart->US_IER = AT91RM9200_US_INT_RXRDY | AT91RM9200_US_INT_PARE |AT91RM9200_US_INT_FRAME | AT91RM9200_US_INT_OVRE;  
    976.     pUsart->US_IDR = AT91RM9200_US_INT_TXRDY;      
    977.     /* we only enable receive and error interrupt 
    978.     pUsart->US_IER = AT91RM9200_US_INT_RXRDY | AT91RM9200_US_INT_RXRDY |AT91RM9200_US_INT_PARE | AT91RM9200_US_INT_FRAME |AT91RM9200_US_INT_OVRE; 
    979.     */  
    980.     intEnable (pParas->intLevel);  
    981.     }  
    982.     else  
    983.     {  
    984.     /* switch device to polled mode */  
    985.   
    986.     /* disable interrupt of device */  
    987.     pUsart->US_IDR = -1;     /* disable all interrupt */  
    988.     intDisable (pParas->intLevel);  
    989.     }  
    990.   
    991.     /* activate  the new mode */  
    992.   
    993.     pChan->mode = newMode;  
    994.   
    995.     intUnlock(oldIntLvl);  
    996.   
    997.     return (OK);  
    998.     }  
    999.   
    1000. #if 0  
    1001. /******************************************************************************* 
    1002. * templateHup - hang up the modem control lines  
    1003. * Resets the RTS and DTR signals. 
    1004. * RETURNS: OK always. 
    1005. */  
    1006.   
    1007. LOCAL STATUS at91Hup  
    1008.     (  
    1009.     AT91_UART_CHAN * pChan  /* pointer to channel */  
    1010.     )  
    1011.     {  
    1012.     /* 
    1013.      * TODO - Use global intLock if lockout time will be very short. If not, 
    1014.      * use a device specific lockout that will not damage overall system 
    1015.      * latency. 
    1016.      */  
    1017.   
    1018.     at91MstatSetClr (pChan,(SIO_MODEM_RTS|SIO_MODEM_DTR), FALSE);  
    1019.   
    1020.     return (OK);  
    1021.     }      
    1022.   
    1023.   
    1024. /******************************************************************************* 
    1025. * at91Open - Set the modem control lines  
    1026. * Set the modem control lines(RTS, DTR) TRUE if not already set.   
    1027. * RETURNS: OK 
    1028. */  
    1029.   
    1030. LOCAL STATUS at91Open  
    1031.     (  
    1032.     AT91_UART_CHAN * pChan  /* pointer to channel */  
    1033.     )  
    1034.     {  
    1035.     /* 
    1036.      * TODO - Use global intLock if lockout time will be very short. If not, 
    1037.      * use a device specific lockout that will not damage overall system 
    1038.      * latency. 
    1039.      */  
    1040.   
    1041.     at91MstatSetClr (pChan, (SIO_MODEM_RTS|SIO_MODEM_DTR), TRUE);  
    1042.   
    1043.     return (OK);  
    1044.     }  
    1045. #endif  
    1046.   
    1047.   
    1048. /****************************************************************************** 
    1049. * at91OptSet - set hardware options 
    1050. * This routine sets up the hardware according to the specified option 
    1051. * argument.  If the hardware cannot support a particular option value, then 
    1052. * it should ignore that portion of the request. 
    1053. * RETURNS: OK upon success, or EIO for invalid arguments. 
    1054. */  
    1055.   
    1056. LOCAL int at91OptSet  
    1057.     (  
    1058.     AT91_UART_CHAN * pChan,     /* channel */  
    1059.     uint_t      newOpts             /* new options */  
    1060.     )  
    1061.     {  
    1062.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */  
    1063.     AT91_UART_PARAS *pParas =  (AT91_UART_PARAS *)(pChan->pUart);  
    1064.   
    1065.     int uartHwOptions = pParas->uartOption;  
    1066. /* 
    1067.     BOOL hdweFlowCtrl=TRUE; 
    1068.     BOOL rcvrEnable = TRUE; 
    1069. */  
    1070.     int  oldIntLvl;  
    1071.   
    1072.     if (pChan == NULL || newOpts & 0xffffff00)  
    1073.     return EIO;  
    1074.   
    1075.     /* do nothing if options already set */  
    1076.   
    1077.     if (pParas->uartOption== newOpts)  
    1078.     return OK;  
    1079.   
    1080.     /* ignore requests for unsupported options */  
    1081.   
    1082.     /* decode individual request elements */  
    1083.       
    1084.     uartHwOptions &= ~(AT91RM9200_US_MR_CHRL);   
    1085.   
    1086.     switch (newOpts & CSIZE)  
    1087.     {  
    1088.     case CS5:  
    1089.         uartHwOptions |= AT91RM9200_US_MR_CHRL_5_BITS;  
    1090.         break;  
    1091.     case CS6:  
    1092.         uartHwOptions |= AT91RM9200_US_MR_CHRL_6_BITS;  
    1093.         break;  
    1094.     case CS7:  
    1095.         uartHwOptions |= AT91RM9200_US_MR_CHRL_7_BITS;  
    1096.         break;  
    1097.     default:  
    1098.     case CS8:  
    1099.         uartHwOptions |= AT91RM9200_US_MR_CHRL_8_BITS;  
    1100.         break;  
    1101.     }  
    1102.   
    1103.     uartHwOptions &= ~(AT91RM9200_US_MR_NBSTOP);  
    1104.   
    1105.     if (newOpts & STOPB)  
    1106.             /* 2 bits stop bit */  
    1107.         uartHwOptions |= AT91RM9200_US_MR_NBSTOP_2_BIT;  
    1108.     else  
    1109.             /* 1 bit stop bit */  
    1110.         uartHwOptions |= AT91RM9200_US_MR_NBSTOP_1_BIT;  
    1111.   
    1112.     uartHwOptions &= ~(AT91RM9200_US_MR_PAR);  
    1113.   
    1114.     switch (newOpts & (PARENB|PARODD))  
    1115.     {  
    1116.     case PARENB|PARODD:  
    1117.         /* enable odd parity */  
    1118.         uartHwOptions |= AT91RM9200_US_MR_PAR_ODD;  
    1119.         break;  
    1120.   
    1121.     case PARENB:  
    1122.         /* enable even parity */  
    1123.         uartHwOptions |= AT91RM9200_US_MR_PAR_EVEN;  
    1124.         break;  
    1125.   
    1126.     case PARODD:  
    1127.         /* invalid mode, not normally used. */  
    1128.         uartHwOptions |= AT91RM9200_US_MR_PAR_MULTI_DROP;  
    1129.         break;  
    1130.   
    1131.     default:  
    1132.     case 0:  
    1133.         /* no parity */;   
    1134.         uartHwOptions |= AT91RM9200_US_MR_PAR_NONE;  
    1135.         break;  
    1136.     }  
    1137.   
    1138.     if (newOpts & CLOCAL)  
    1139.     {  
    1140.   
    1141.     /* clocal disables hardware flow control */  
    1142.     uartHwOptions &= ~(AT91RM9200_US_MR_USMODE);  
    1143.     uartHwOptions |= AT91RM9200_US_MR_USMODE_NORMAL;  
    1144.     }  
    1145.     else  
    1146.         {  
    1147.         /* enable hardware flow control */  
    1148.     uartHwOptions &= ~(AT91RM9200_US_MR_USMODE);  
    1149.         uartHwOptions |= AT91RM9200_US_MR_USMODE_HWHSH;  
    1150.         uartHwOptions |= AT91RM9200_US_MR_USMODE_MODEM;  
    1151.         }  
    1152.   
    1153.   
    1154.     if ((newOpts & CREAD) == 0)  
    1155.     pUsart->US_CR = AT91RM9200_US_CR_RXDIS;  
    1156.     else  
    1157.         pUsart->US_CR = AT91RM9200_US_CR_RXEN;  
    1158.   
    1159.     oldIntLvl = intLock ();  
    1160.   
    1161.     /* 
    1162.      * Reset the device according to uartHwOptions 
    1163.      */  
    1164.   
    1165.     pUsart->US_MR = uartHwOptions;  
    1166.       
    1167.     intUnlock (oldIntLvl);  
    1168.   
    1169.     /* 
    1170.      * Be sure that pChan->options reflects the actual 
    1171.      * hardware settings.  If 5 data bits were requested, but unsupported, 
    1172.      * then be sure pChan->options reflects the actual number of data bits 
    1173.      * currently selected. 
    1174.      */  
    1175.   
    1176.     /*  
    1177.      * we store register setting in pParas->uartOption 
    1178.      * and software setting in pChan->options 
    1179.      */  
    1180.     pParas->uartOption = uartHwOptions;  
    1181.     pChan->options = newOpts;  
    1182.   
    1183.     return (OK);  
    1184.     }  
    1185.   
    1186. /******************************************************************************* 
    1187. * at91Ioctl - special device control 
    1188. * This routine handles the IOCTL messages from the user. It supports commands  
    1189. * to get/set baud rate, mode(INT,POLL), hardware options(parity, number of  
    1190. * data bits) and modem control(RTS/CTS and DTR/DSR handshakes). 
    1191. * The ioctl commands SIO_HUP and SIO_OPEN are used to implement the HUPCL(hang 
    1192. * up on last close) function. 
    1193. * As on a UNIX system, requesting a baud rate of zero is translated into 
    1194. * a hangup request.  The DTR and RTS lines are dropped.  This should cause 
    1195. * a connected modem to drop the connection.  The SIO_HUP command will only 
    1196. * hangup if the HUPCL option is active.  The SIO_OPEN function will raise 
    1197. * DTR and RTS lines whenever it is called. Use the BAUD_RATE=0 function 
    1198. * to hangup when HUPCL is not active. 
    1199. * The CLOCAL option will disable hardware flow control.  When selected, 
    1200. * hardware flow control is not used.  When not selected hardware flow control 
    1201. * is based on the RTS/CTS signals.  CTS is the clear to send input 
    1202. * from the other end.  It must be true for this end to begin sending new 
    1203. * characters.  In most drivers, the RTS signal will be assumed to be connected 
    1204. * to the opposite end's CTS signal and can be used to control output from 
    1205. * the other end.  Raising RTS asserts CTS at the other end and the other end 
    1206. * can send data.  Lowering RTS de-asserts CTS and the other end will stop 
    1207. * sending data. (This is non-EIA defined use of RTS). 
    1208. * RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed 
    1209. * request. 
    1210. */  
    1211.   
    1212. LOCAL int at91Ioctl  
    1213.     (  
    1214.     SIO_CHAN *  pSioChan,       /* device to control */  
    1215.     int     request,        /* request code */  
    1216.     void *  someArg         /* some argument */  
    1217.     )  
    1218.     {  
    1219.     AT91_UART_CHAN *pChan = (AT91_UART_CHAN *) pSioChan;  
    1220.     AT91PS_USART pUsart = (AT91PS_USART)(pChan->ioBase); /* point to UART register index by ioBase of pChan */  
    1221.     AT91_UART_PARAS *pParas =  (AT91_UART_PARAS *)(pChan->pUart);  
    1222.   
    1223.     int     oldLevel;       /* current interrupt level mask */  
    1224.     int     baudConstant;  
    1225.     int     arg = (int)someArg;  
    1226.   
    1227.     /* TEMPLATE_PIPE_FLUSH(pChan); */  
    1228.     switch (request)  
    1229.     {  
    1230.     case SIO_BAUD_SET:  
    1231.   
    1232.         /* 
    1233.          * like unix, a baud request for 0 is really a request to hangup. 
    1234.          */  
    1235.   
    1236.         if (arg == 0)  
    1237.         return (EIO);  
    1238.           
    1239.         /* return (at91Hup (pChan)); */  
    1240.   
    1241.         /* 
    1242.          * Set the baud rate. Return EIO for an invalid baud rate, or 
    1243.          * OK on success. 
    1244.          */  
    1245.   
    1246.         if (arg < AT91_BAUD_MIN || arg > AT91_BAUD_MAX)  
    1247.             {  
    1248.         return (EIO);  
    1249.             }  
    1250.   
    1251.         /* Calculate the baud rate constant for the new baud rate */  
    1252.   
    1253.         baudConstant = AT91_MASTER_CLOCK / arg / 16;   
    1254.           
    1255.   
    1256.         /* disable interrupts during chip access */  
    1257.   
    1258.         oldLevel = intLock ();  
    1259.         pUsart->US_BRGR = baudConstant;  
    1260.         intUnlock (oldLevel);  
    1261.   
    1262.         pParas->baudRate = arg;  
    1263.   
    1264.         return (OK);  
    1265.   
    1266.     case SIO_BAUD_GET:  
    1267.   
    1268.         *(int *)someArg = pParas->baudRate;  
    1269.         return (OK);  
    1270.   
    1271.     case SIO_MODE_SET:  
    1272.   
    1273.         /* 
    1274.          * Set the mode (e.g., to interrupt or polled). Return OK 
    1275.          * or EIO for an unknown or unsupported mode. 
    1276.          */  
    1277.   
    1278.         return (at91ModeSet (pChan, arg));  
    1279.   
    1280.     case SIO_MODE_GET:  
    1281.   
    1282.         /* Get the current mode and return OK.  */  
    1283.   
    1284.         *(int *)someArg = pChan->mode;  
    1285.         return (OK);  
    1286.   
    1287.     case SIO_AVAIL_MODES_GET:  
    1288.   
    1289.         /* TODO - set the available modes and return OK.  */  
    1290.   
    1291.         *(int *)someArg = SIO_MODE_INT | SIO_MODE_POLL;  
    1292.         return (OK);  
    1293.   
    1294.     case SIO_HW_OPTS_SET:  
    1295.   
    1296.         /* 
    1297.          * Optional command to set the hardware options (as defined 
    1298.          * in sioLib.h). 
    1299.          * Return OK, or ENOSYS if this command is not implemented. 
    1300.          * Note: several hardware options are specified at once. 
    1301.          * This routine should set as many as it can and then return 
    1302.          * OK. The SIO_HW_OPTS_GET is used to find out which options 
    1303.          * were actually set. 
    1304.          */  
    1305.   
    1306.         return (at91OptSet (pChan, arg));  
    1307.   
    1308.     case SIO_HW_OPTS_GET:  
    1309.   
    1310.         /* 
    1311.          * Optional command to get the hardware options (as defined 
    1312.          * in sioLib.h). Return OK or ENOSYS if this command is not 
    1313.          * implemented.  Note: if this command is unimplemented, it 
    1314.          * will be assumed that the driver options are CREAD | CS8 
    1315.          * (e.g., eight data bits, one stop bit, no parity, ints enabled). 
    1316.          */  
    1317.   
    1318.         *(int *)someArg = pChan->options;  
    1319.         return (OK);  
    1320.           
    1321. #if 0  
    1322.         case SIO_HUP:  
    1323.   
    1324.             /* check if hupcl option is enabled */  
    1325.   
    1326.             if (pChan->options & HUPCL)   
    1327.                 return (at91Hup (pChan));  
    1328.             return (OK);  
    1329.   
    1330.         case SIO_OPEN:  
    1331.         return (at91Open (pChan)); /* always open */  
    1332. #endif  
    1333.   
    1334. #if 0 /* TODO - optional modem control line support */  
    1335.   
    1336.     /* 
    1337.      * These new ioctl commands are for monitoring and setting the 
    1338.      * state of the modem control lines under user control. The 
    1339.      * return values from these calls inform the user about which 
    1340.      * control lines are inputs and which are outputs. Basically 
    1341.      * this lets the user know if the device is wired for DTE or 
    1342.      * DCE configuration.  It also informs the user if any signals 
    1343.      * are missing altogether. 
    1344.      */  
    1345.   
    1346.     case SIO_MSTAT_GET:  
    1347.         return templateMstatGet(pChan);  
    1348.   
    1349.     case SIO_MCTRL_BITS_SET:  
    1350.         return templateMstatSetClr (pChan, arg, TRUE);  
    1351.   
    1352.     case SIO_MCTRL_BITS_CLR:  
    1353.         return templateMstatSetClr (pChan, arg, FALSE);  
    1354.   
    1355.     /* 
    1356.      * The ISIG and OSIG masks tell the user which signals are actually 
    1357.      * outputs and which aren't. In our case here, we assume the device 
    1358.      * is DTE mapped with DTR and RTS as outputs. DSR and CTS as inputs. 
    1359.      * This template driver doesn't support RI. 
    1360.      */  
    1361.     case SIO_MCTRL_OSIG_MASK:  
    1362.         *(int *)someArg = TEMPLATE_OSIG_MASK;  
    1363.         break;  
    1364.   
    1365.     case SIO_MCTRL_ISIG_MASK:  
    1366.         *(int *)someArg = TEMPLATE_ISIG_MASK;  
    1367.         break;  
    1368.   
    1369. #endif /* optional Modem control line support */  
    1370.   
    1371. #if 0 /* TODO - optional keyboard scan code support */  
    1372.   
    1373.     /* 
    1374.      * The following new ioctl commands are meant only for keyboard 
    1375.      * input devices to use.  These allow the user to specify and 
    1376.      * examine the type of keyboard character mapping to use.  The 
    1377.      * possible types are NONE (raw scan codes), ASCII (default ascii 
    1378.      * mappings, and UNICODE for standard 16 bit unicode mappings. 
    1379.      * 
    1380.      * Our template driver supports only raw and ascii modes. 
    1381.      */  
    1382.   
    1383.     case SIO_KYBD_MODE_SET:  
    1384.         switch (arg)  
    1385.         {  
    1386.         case SIO_KYBD_MODE_RAW:  
    1387.         case SIO_KYBD_MODE_ASCII:  
    1388.             break;  
    1389.   
    1390.         case SIO_KYBD_MODE_UNICODE:  
    1391.             return ENOSYS; /* template doesn't support unicode */  
    1392.         }  
    1393.         pChan->scanMode = arg;  
    1394.         return OK;  
    1395.   
    1396.     case SIO_KYBD_MODE_GET:  
    1397.         *(int *)someArg = pChan->scanMode;  
    1398.         return OK;  
    1399.   
    1400. #endif /* optional keyboard scan code support */  
    1401.   
    1402.     default:  
    1403.         return ENOSYS;  
    1404.     }  
    1405.     return OK;  
    1406.     }  
    1407.   
    1408. /******************************************************************************* 
    1409. * dummyTxCallback - dummy Tx callback routine 
    1410. * RETURNS: ERROR. 
    1411. */  
    1412.   
    1413. LOCAL STATUS at91DummyTxCallback  
    1414.     (  
    1415.     void * callbackArg, /* argument registered with callback */  
    1416.     char * pChara   /* ptr to data location */  
    1417.     )  
    1418.     {  
    1419.     static BOOL doit = TRUE;  
    1420.   
    1421.     /* 
    1422.      * TODO - Until an upstream module connects to this device, there 
    1423.      * is no data available to send.  We should only be concerned 
    1424.      * if this callback is being called repeatedly and often. That 
    1425.      * could indicate an interrupt servicing problem of some kind. 
    1426.      */  
    1427.   
    1428.     if (doit)  
    1429.     {  
    1430.     printf ("Dummy txCallback: 0x%x 0x%x ",  
    1431.         (int)callbackArg, (int)pChara);  
    1432.     doit = FALSE;  
    1433.     }  
    1434.   
    1435.     return (ERROR);  
    1436.     }  
    1437.   
    1438. /******************************************************************************* 
    1439. * dummyRxCallback - dummy Rx callback routine 
    1440. * RETURNS: N/A. 
    1441. * ARGSUSED 
    1442. */  
    1443.   
    1444. LOCAL void at91DummyRxCallback  
    1445.     (  
    1446.     void * callbackArg, /* argument registered with callback */  
    1447.     char data       /* receive data */  
    1448.     )  
    1449.     {  
    1450.     static BOOL doit = TRUE;  
    1451.   
    1452.     /* 
    1453.      * TODO - Device is transferring data, but there is no 
    1454.      * upstream module connected to receive it.  Lets log 
    1455.      * a message about incoming data being lost.  Buts lets 
    1456.      * do this only once we don't want a 'flood' of logged 
    1457.      * messages. 
    1458.      */  
    1459.   
    1460.     if (doit)  
    1461.     {  
    1462.     printf ("Dummy rxCallback: 0x%x 0x%x ",  
    1463.         (int)callbackArg, (int)data);  
    1464.     doit = FALSE;  
    1465.     }  
    1466.   
    1467.     return;  
    1468.     }  
    1469.   
    1470. /******************************************************************************* 
    1471. * dummyErrCallback - dummy Error callback routine 
    1472. * There should be an sioLib module to provide dummyCallbacks for all SIO 
    1473. * drivers to use. 
    1474. * RETURNS: N/A. 
    1475. * ARGSUSED 
    1476. */  
    1477.   
    1478. LOCAL void at91DummyErrCallback  
    1479.     (  
    1480.     void * callbackArg, /* argument registered with callback */  
    1481.     int errorCode,  /* error code */  
    1482.     void * pData,   /* ptr to device specific data */  
    1483.     int size        /* size of device specific data */  
    1484.     )  
    1485.     {  
    1486.     static BOOL doit = TRUE;  
    1487.   
    1488.     /* TODO -  We could log the reported error (once). */  
    1489.   
    1490.     if (doit)  
    1491.     {  
    1492.     printf ("Dummy errorCallback: 0x%x 0x%x 0x%x %d ",  
    1493.         (int)callbackArg, errorCode, (int)pData, size);  
    1494.     doit = FALSE;  
    1495.     }  
    1496.   
    1497.     return;  
    1498.     }  
    1499.   
    1500. /******************************************************************************* 
    1501. * at91Probe - probe for device  
    1502. * Try to determine if device is present.  Do not reconfigure device if it 
    1503. * is there.  This should be a passive probe that does not interfere with 
    1504. * the device. 
    1505. * RETURNS: 
    1506. * Returns OK if device adaptor is there, ERROR if not there. 
    1507. */  
    1508.   
    1509. LOCAL STATUS at91Probe  
    1510.     (  
    1511.     AT91_UART_CHAN * pChan /* channel to probe */  
    1512.     )  
    1513.     {  
    1514.     /*  
    1515.      * the UART and DBGU is internal controller of AT91RM9200 CPU,  
    1516.      * so we needn't to probe it 
    1517.      */   
    1518.     return OK;  
    1519.     }  
    1520.   
    1521. #if 0  
    1522. /******************************************************************************* 
    1523. * at91Verify - verify at91_uart chan structure 
    1524. * Given a pointer to what should be a AT91_UART_CHAN, verify that it really 
    1525. * is a AT91_UART_CHAN structure. 
    1526. * This routine should not be called at every level with every routine.  It is 
    1527. * primarily provided for use with the xxxDestroy routine.  Performance will be 
    1528. * a problem if every pointer is checked for validity with every use. 
    1529. * RETURNS: 
    1530. * Returns OK if pointer is valid, ERROR if not. 
    1531. */  
    1532.   
    1533. LOCAL STATUS at91Verify  
    1534.     (  
    1535.     AT91_UART_CHAN * pChan /* pointer to be verified */  
    1536.     )  
    1537.     {  
    1538.     /* 
    1539.      * Examine the structure. Look for magic cookies or flag bits. 
    1540.      * Anything that would confirm this pointer as being a valid 
    1541.      * AT91_UART_CHAN pointer. 
    1542.      */  
    1543.   
    1544.     if (pChan == NULL)  
    1545.     return ERROR;  
    1546.   
    1547.     return OK;  
    1548.     }  
    1549.   
    1550. #endif  
    1551.   
    1552. #if 0 /* Optional modem control line support */  
    1553.   
    1554. /******************************************************************************* 
    1555. * at91MstatGet - read device modem control line status 
    1556. * Read the device modem control lines and map them to the standard 
    1557. * modem signal bits. 
    1558. * RETURNS: 
    1559. * Returns the modem control line status bits. 
    1560. */  
    1561.   
    1562. LOCAL int at91MstatGet  
    1563.     (  
    1564.     AT91_UART_CHAN *pChan  
    1565.     )  
    1566.     {  
    1567.     AT91_UART_CHAN * pChan = (AT91_UART_CHAN *)pSioChan;  
    1568.     UINT32  status;  
    1569.     int result = 0;  
    1570.   
    1571.     AT91PS_USART pUsart;    /* point to UART register index by ioBase of pChan */  
    1572.   
    1573.     pUsart = (AT91PS_USART)(pChan->ioBase);  
    1574.   
    1575.     /* Read RX device status */  
    1576.   
    1577.     status = pUsart->US_CSR;  
    1578.     /* Now map device status bits, to standard status bits */  
    1579.   
    1580.     if (rawStatus & TEMPLATE_MSR_CD)  
    1581.     result |= SIO_MODEM_CD;  
    1582.   
    1583.     if (rawStatus & TEMPLATE_MSR_DTR)  
    1584.     result |= SIO_MODEM_DTR;  
    1585.   
    1586.     if (rawStatus & TEMPLATE_MSR_DSR)  
    1587.     result |= SIO_MODEM_DSR;  
    1588.   
    1589.     if (rawStatus & TEMPLATE_MSR_RTS)  
    1590.     result |= SIO_MODEM_RTS;  
    1591.   
    1592.     if (rawStatus & TEMPLATE_MSR_CTS)  
    1593.     result |= SIO_MODEM_CTS;  
    1594.   
    1595.     return result;  
    1596.     }  
    1597.   
    1598. /******************************************************************************* 
    1599. * templateMstatSetClear - set/clear modem control lines 
    1600. * This routine allows the user to set or clear individual modem control 
    1601. * lines.  Of course, only the output lines can actually be changed. 
    1602. * RETURNS: 
    1603. * OK, or EIO upon detecting a hardware fault. 
    1604. */  
    1605.   
    1606. LOCAL int templateMstatSetClr  
    1607.     (  
    1608.     TEMPLATE_CHAN *pChan,  
    1609.     UINT bits,      /* bits to change */  
    1610.     BOOL setFlag    /* TRUE = set, FALSE = clear */  
    1611.     )  
    1612.     {  
    1613.     UINT8 rawStatus;  
    1614.     UINT8 rawMask = 0;  
    1615.   
    1616.     /* Read current modem status */  
    1617.     TEMPLATE_SIO_READ8 (pChan, TEMPLATE_MSR_ID, &rawStatus);  
    1618.   
    1619.     /* ignore input only bits */  
    1620.     bits &= TEMPLATE_OSIG_MASK;  
    1621.   
    1622.     /* Now map standard bits to device specific bits */  
    1623.   
    1624.     if (bits & SIO_MODEM_DTR)  
    1625.     rawMask |= TEMPLATE_MSR_DTR;  
    1626.   
    1627.     if (bits & SIO_MODEM_RTS)  
    1628.     rawMask |= TEMPLATE_MSR_RTS;  
    1629.   
    1630.     /* Update device with new output signals */  
    1631.   
    1632.     if (setFlag)  
    1633.     rawStatus |= rawMask; /* set new bits */  
    1634.     else  
    1635.     rawStatus &= ~rawMask; /* clear bits */  
    1636.   
    1637.     TEMPLATE_SIO_WRITE8 (pChan, TEMPLATE_MSR_ID, rawStatus);  
    1638.   
    1639.     return OK;  
    1640.     }  
    1641. #endif /* optional modem control line support */  
     

  • 相关阅读:
    从源码解读Spring如何解决bean循环依赖
    前后端分离下用jwt做用户认证
    断点调试获取程序当前位置的运行结果
    Win10安装MySQL8压缩包版
    IDEA实用快捷键推荐
    多平台博客发布工具OpenWrite的使用
    Tomcat部署多个war包
    从储值卡(会员卡)充值业务看分布式事务的设计
    再谈 PHP 未来之路
    Swoole 实战:MySQL 查询器的实现(协程连接池版)
  • 原文地址:https://www.cnblogs.com/zym0805/p/4815535.html
Copyright © 2011-2022 走看看