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 "arch\arm\ivarm.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\n",  
  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\n",  
  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\n",  
  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 */  
 

posted on 2015-09-17 10:26  嵌入式操作系统  阅读(657)  评论(0编辑  收藏  举报

导航