at91 uart driver for vxworks

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

时间: 2024-10-10 10:45:22

at91 uart driver for vxworks的相关文章

Android bluetooth介绍(二): android 蓝牙代码架构及其uart 到rfcomm流程

关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP RFCOMM  版本:基于android4.2之前版本 bluez内核:linux/linux3.08系统:android/android4.1.3.4作者:xubin341719(欢迎转载,请注明作者,请尊重版权谢谢)欢迎指正错误,共同学习.共同进步!!一.Android Bluetooth Architecture蓝牙代码架构部分(google 官方蓝牙框架) Android的蓝牙系统,自下而上包括以下一些

tty初探—uart驱动框架分析(二)uart_add_one_port

在前面的一篇文章中,我们分析了一个 uart_driver 的向上注册过程,主要是 tty 的一些东西,知道了 tty 注册了一个字符设备驱动,我们在用户空间 open 时将调用到 uart_port.ops.startup ,在用户空间 write 则调用 uart_port.ops.start_tx ,还知道了如何 read 数据等等.但是,这些都是内核帮我们实现好的,在真正的驱动开发过程中几乎不涉及那些代码的修改移植工作,真正需要我们触碰的是 uart_port 这个结构体,它真正的对应于

Linux kernel 之 uart 驱动解析

uart 是一种非常之常见的总线,比如DEBUG信息输出,小数据量数据传输,485,以及蓝牙的控制,GPS,很多都是通过uart 进行数据传输并进行控制. 在Linux kernel 内部,uart 通常是作为 一个 tty 设备对其进行控制,也是就是一个字符设备文件,可对其进行读写操作. kernel version 4.4.12 首先先看一下基本的 结构体 和 API 操作. // include/linux/serial_core.h // uart 驱动结构体 struct uart_d

tty初探—uart驱动框架分析

本文参考了大量牛人的博客,对大神的分享表示由衷的感谢. 主要参考: tty驱动分析 :http://www.wowotech.net/linux_kenrel/183.html Linux TTY驱动--Uart_driver底层:http://blog.csdn.net/sharecode/article/details/9196591 Linux TTY驱动--Serial Core层  :http://blog.csdn.net/sharecode/article/details/9197

Android bluetooth介绍(两): android 蓝牙源架构和uart 至rfcomm过程

关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP RFCOMM  版本号:基于android4.2先前版本 bluez内核:linux/linux3.08系统:android/android4.1.3.4作者:xubin341719(欢迎转载,请注明作者.请尊重版权谢谢)欢迎指正错误,共同学习.共同进步!! Android bluetooth介绍(一):基本概念及硬件接口Android bluetooth介绍(二): android 蓝牙代码架构及其uart

Raspberry Pi 3 with Openwrt

https://wiki.openwrt.org/toh/raspberry_pi_foundation/raspberry_pi#boot_log_raspberry_pi_3 Table of Contents Supported Versions Hardware Specifications Raspberry Pi SoCs Raspberry Pi Models Using I2C and SPI Power Notes Serial Boot Logs Boot Log (Rasp

[i.MX6q]i.MX6q处理器,linux操作系统平台搭建 从SD卡启动系统

转自:http://www.07net01.com/linux/2016/02/1232094.html 参照1:http://blog.csdn.net/girlkoo/article/details/44536447 参照2:http://blog.csdn.net/girlkoo/article/details/44626011 2017-02-04 22:52:54 目录: 本文的目的是,完成一个从sd卡启动的一个纯净版的linux系统移植,其实就是一个很裸的根文件系统,后期有空会试着把

Smart210学习记录------linux串口驱动

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=27025492&id=327609 一.核心数据结构 串口驱动有3个核心数据结构,它们都定义在<#include linux/serial_core.h> 1.uart_driver uart_driver包含了串口设备名.串口驱动名.主次设备号.串口控制台(可选)等信息,还封装了tty_driver(底层串口驱动无需关心tty_driver). struct

在qemu上运行linux

1,安装工具sudo apt-get install gcc-arm-linux-gnueabisudo apt-get install qemu 2,下载Linux内核从kernel.org下载压缩包tar -xf linux-3.16.45.tar.xz 3,编译内核make mrproper #可选,保证原始干净环境 生成vexpress开发板子的config文件:make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconf