]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/pxa27x/uart/HalPXA27xSerialP.nc
Convert to Unix-style line terminators.
[tinyos-2.x.git] / tos / chips / pxa27x / uart / HalPXA27xSerialP.nc
index f98f4f41bcd0fe65b040877a2421f78db4840c0b..e788cef5140b788c408a6d13e8b1ae89950bc1b8 100644 (file)
-/* $Id$ */\r
-/*\r
- * Copyright (c) 2005 Arched Rock Corporation \r
- * All rights reserved. \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are\r
- * met:\r
- *     Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- *     Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- *  \r
- *   Neither the name of the Arched Rock Corporation nor the names of its\r
- * contributors may be used to endorse or promote products derived from\r
- * this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ARCHED\r
- * ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\r
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\r
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\r
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\r
- * DAMAGE.\r
- */\r
-/*\r
- *  Intel Open Source License\r
- *\r
- *  Copyright (c) 2002 Intel Corporation\r
- *  All rights reserved.\r
- *  Redistribution and use in source and binary forms, with or without\r
- *  modification, are permitted provided that the following conditions are\r
- *  met:\r
- *\r
- *     Redistributions of source code must retain the above copyright\r
- *  notice, this list of conditions and the following disclaimer.\r
- *     Redistributions in binary form must reproduce the above copyright\r
- *  notice, this list of conditions and the following disclaimer in the\r
- *  documentation and/or other materials provided with the distribution.\r
- *      Neither the name of the Intel Corporation nor the names of its\r
- *  contributors may be used to endorse or promote products derived from\r
- *  this software without specific prior written permission.\r
- *\r
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\r
- *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS\r
- *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
- *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
- *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
- *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- *\r
- */\r
-/**\r
- * Implements the UartByte, UartStream and HalPXA27xSerialPacket interface \r
- * for a PXA27x UART. \r
- * \r
- *\r
- * @param defaultRate Default baud rate for the serial port. \r
- *\r
- *\r
- * @author Phil Buonadonna\r
- */\r
-\r
-#include "pxa27x_serial.h"\r
-\r
-generic module HalPXA27xSerialP(uint32_t defaultRate)\r
-{\r
-  provides {\r
-    interface Init;\r
-    interface StdControl;\r
-    interface UartByte;\r
-    interface UartStream;\r
-    interface HalPXA27xSerialPacket;\r
-    interface HalPXA27xSerialCntl;\r
-  }\r
-  uses {\r
-    interface Init as UARTInit;\r
-    interface HplPXA27xUART as UART;\r
-    interface HplPXA27xDMAChnl as RxDMA;\r
-    interface HplPXA27xDMAChnl as TxDMA;\r
-    interface HplPXA27xDMAInfo as UARTRxDMAInfo;\r
-    interface HplPXA27xDMAInfo as UARTTxDMAInfo;\r
-  }\r
-}\r
-\r
-implementation \r
-{\r
-\r
-  uint8_t *txCurrentBuf, *rxCurrentBuf;\r
-  uint32_t txCurrentLen, rxCurrentLen, rxCurrentIdx;\r
-  uint32_t gulFCRShadow;\r
-  bool gbUsingUartStreamSendIF = FALSE;\r
-  bool gbUsingUartStreamRcvIF = FALSE;\r
-  bool gbRcvByteEvtEnabled = TRUE;\r
-\r
-  command error_t Init.init() {\r
-    error_t error = SUCCESS;\r
-\r
-    atomic {\r
-      call UARTInit.init();\r
-      txCurrentBuf = rxCurrentBuf = NULL;\r
-      gbUsingUartStreamSendIF = FALSE;\r
-      gbUsingUartStreamRcvIF = FALSE;\r
-      gbRcvByteEvtEnabled = TRUE;\r
-      gulFCRShadow = (FCR_TRFIFOE | FCR_ITL(0)); // FIFO Mode, 1 byte Rx threshold\r
-    }\r
-    call TxDMA.setMap(call UARTTxDMAInfo.getMapIndex());\r
-    call RxDMA.setMap(call UARTRxDMAInfo.getMapIndex());\r
-    call TxDMA.setDALGNbit(TRUE);\r
-    call RxDMA.setDALGNbit(TRUE);\r
-\r
-    error = call HalPXA27xSerialCntl.configPort(defaultRate,8,NONE,1,FALSE);\r
-    \r
-    atomic {call UART.setFCR(gulFCRShadow);}\r
-    return error;\r
-  }\r
-\r
-  command error_t StdControl.start() {\r
-    atomic {\r
-      call UART.setIER(IER_UUE | IER_RAVIE);\r
-    }\r
-    return SUCCESS;\r
-  }\r
-\r
-  command error_t StdControl.stop() {\r
-    atomic {\r
-      call UART.setIER(0);\r
-    }\r
-    return SUCCESS;\r
-  }\r
-\r
-  async command error_t UartByte.send(uint8_t data) {\r
-    atomic call UART.setTHR(data);\r
-    while ((call UART.getLSR() & LSR_TEMT) == 0);\r
-    return SUCCESS;\r
-  }\r
-\r
-  async command error_t UartByte.receive( uint8_t *data, uint8_t timeout) {\r
-    error_t error = FAIL;\r
-    uint8_t t;\r
-    for (t = 0; t < timeout; t++) {\r
-      if (call UART.getLSR() & LSR_DR) {\r
-       *data = call UART.getRBR();\r
-       error = SUCCESS;\r
-       break;\r
-      }\r
-    }\r
-    return error;\r
-  }\r
-\r
-  async command error_t UartStream.send( uint8_t* buf, uint16_t len ) {\r
-    error_t error;\r
-    atomic gbUsingUartStreamSendIF = TRUE;\r
-    error = call HalPXA27xSerialPacket.send(buf,len);\r
-    if (error) {\r
-      atomic gbUsingUartStreamSendIF = FALSE;\r
-    }\r
-    return error;\r
-  }\r
-\r
-\r
-  async command error_t UartStream.enableReceiveInterrupt() {\r
-    error_t error = SUCCESS;\r
-    atomic {\r
-      if (rxCurrentBuf == NULL) {\r
-       call UART.setIER(call UART.getIER() | IER_RAVIE);\r
-      }\r
-      gbRcvByteEvtEnabled = TRUE;\r
-    }\r
-    return SUCCESS;\r
-  }\r
-\r
-  async command error_t UartStream.disableReceiveInterrupt() {\r
-    atomic {\r
-      // Check to make sure a short stream/packet call isn't in progress\r
-      if ((rxCurrentBuf == NULL) || (rxCurrentLen >= 8)) {\r
-       call UART.setIER(call UART.getIER() & ~IER_RAVIE);\r
-      }\r
-      gbRcvByteEvtEnabled = FALSE;\r
-    }\r
-    return SUCCESS;\r
-  }\r
-\r
-  async command error_t UartStream.receive( uint8_t* buf, uint16_t len ) {\r
-    error_t error;\r
-    atomic gbUsingUartStreamRcvIF = TRUE;\r
-    error = call HalPXA27xSerialPacket.receive(buf,len,0);\r
-    if (error) {\r
-      atomic gbUsingUartStreamRcvIF = FALSE;\r
-    }\r
-    return error;\r
-  }\r
-  \r
-  async command error_t HalPXA27xSerialPacket.send(uint8_t *buf, uint16_t len) {\r
-    uint32_t txAddr;\r
-    uint32_t DMAFlags;\r
-    error_t error = SUCCESS;\r
-\r
-    atomic {\r
-      if (txCurrentBuf == NULL) {\r
-       txCurrentBuf = buf;\r
-       txCurrentLen = len;\r
-      }\r
-      else {\r
-       error = FAIL;\r
-      }\r
-    }\r
-\r
-    if (error) \r
-      return error;\r
-    \r
-    if (len < 8) {\r
-      uint16_t i;\r
-      // Use PIO. Invariant: FIFO is empty\r
-      atomic {\r
-       gulFCRShadow |= FCR_TIL;\r
-       call UART.setFCR(gulFCRShadow); \r
-      }\r
-      for (i = 0;i < len;i++) {\r
-       call UART.setTHR(buf[i]);\r
-      }\r
-      atomic call UART.setIER(call UART.getIER() | IER_TIE);\r
-    }\r
-    else {\r
-      // Use DMA\r
-      DMAFlags = (DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | DCMD_ENDIRQEN\r
-                 | DCMD_LEN(len) );\r
-      \r
-      txAddr = (uint32_t) buf;\r
-      DMAFlags |= DCMD_INCSRCADDR;\r
-      \r
-      call TxDMA.setDCSR(DCSR_NODESCFETCH);\r
-      call TxDMA.setDSADR(txAddr);\r
-      call TxDMA.setDTADR(call UARTTxDMAInfo.getAddr());\r
-      call TxDMA.setDCMD(DMAFlags);\r
-      \r
-      atomic {\r
-       call UART.setIER(call UART.getIER() | IER_DMAE);\r
-      }\r
-\r
-      call TxDMA.setDCSR(DCSR_RUN | DCSR_NODESCFETCH);\r
-    }\r
-    return error;\r
-  }\r
-\r
-\r
-  async command error_t HalPXA27xSerialPacket.receive(uint8_t *buf, uint16_t len, \r
-                                                     uint16_t timeout) {\r
-    uint32_t rxAddr;\r
-    uint32_t DMAFlags;\r
-    error_t error = SUCCESS;\r
-\r
-    atomic {\r
-      if (rxCurrentBuf == NULL) {\r
-       rxCurrentBuf = buf;\r
-       rxCurrentLen = len;\r
-       rxCurrentIdx = 0;\r
-      }\r
-      else {\r
-       error = FAIL;\r
-      }\r
-    }\r
-\r
-    if (error) \r
-      return error;\r
-\r
-    if (len < 8) {\r
-      // Use PIO. Invariant: FIFO is empty\r
-      atomic {\r
-       gulFCRShadow = ((gulFCRShadow & ~(FCR_ITL(3))) | FCR_ITL(0));\r
-       call UART.setFCR(gulFCRShadow); \r
-       call UART.setIER(call UART.getIER() | IER_RAVIE);\r
-      }\r
-    }\r
-    else {\r
-      // Use DMA\r
-      DMAFlags = (DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | DCMD_ENDIRQEN\r
-                 | DCMD_LEN(len) );\r
-      \r
-      rxAddr = (uint32_t) buf;\r
-      DMAFlags |= DCMD_INCTRGADDR;\r
-      \r
-      call RxDMA.setDCSR(DCSR_NODESCFETCH);\r
-      call RxDMA.setDTADR(rxAddr);\r
-      call RxDMA.setDSADR(call UARTRxDMAInfo.getAddr());\r
-      call RxDMA.setDCMD(DMAFlags);\r
-\r
-      atomic {\r
-       gulFCRShadow = ((gulFCRShadow & ~(FCR_ITL(3))) | FCR_ITL(1));\r
-       call UART.setFCR(gulFCRShadow); \r
-       call UART.setIER((call UART.getIER() & ~IER_RAVIE) | IER_DMAE);\r
-      }\r
-\r
-      call RxDMA.setDCSR(DCSR_RUN | DCSR_NODESCFETCH);\r
-    }\r
-    return error;\r
-  }\r
-  \r
-  void DispatchStreamRcvSignal() {\r
-    uint8_t *pBuf = rxCurrentBuf;\r
-    uint16_t len = rxCurrentLen;\r
-    rxCurrentBuf = NULL;\r
-    if (gbUsingUartStreamRcvIF) {\r
-      gbUsingUartStreamRcvIF = FALSE;\r
-      signal UartStream.receiveDone(pBuf, len, SUCCESS);\r
-    }\r
-    else {\r
-      pBuf = signal HalPXA27xSerialPacket.receiveDone(pBuf, len, SUCCESS);\r
-      if (pBuf) {\r
-       call HalPXA27xSerialPacket.receive(pBuf,len,0);\r
-      }\r
-    }\r
-    return;\r
-  }\r
-\r
-  void DispatchStreamSendSignal() {\r
-    uint8_t *pBuf = txCurrentBuf;\r
-    uint16_t len = txCurrentLen;\r
-    txCurrentBuf = NULL;\r
-    if (gbUsingUartStreamSendIF) {\r
-      gbUsingUartStreamSendIF = FALSE;\r
-      signal UartStream.sendDone(pBuf, len, SUCCESS);\r
-    }\r
-    else {\r
-      pBuf = signal HalPXA27xSerialPacket.sendDone(pBuf, len, SUCCESS);\r
-      if (pBuf) {\r
-       call HalPXA27xSerialPacket.send(pBuf,len);\r
-      }\r
-    }\r
-    return;\r
-  }\r
-\r
-  async event void RxDMA.interruptDMA() {\r
-    call RxDMA.setDCMD(0);\r
-    call RxDMA.setDCSR(DCSR_EORINT | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERRINTR);\r
-    DispatchStreamRcvSignal();\r
-    if (gbRcvByteEvtEnabled) \r
-      call UART.setIER(call UART.getIER() | IER_RAVIE);\r
-    return;\r
-  }\r
-\r
-  async event void TxDMA.interruptDMA() {\r
-    call TxDMA.setDCMD(0);\r
-    call TxDMA.setDCSR(DCSR_EORINT | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERRINTR);\r
-    DispatchStreamSendSignal();\r
-    return;\r
-  }\r
-\r
-\r
-  async command error_t HalPXA27xSerialCntl.configPort(uint32_t baudrate, \r
-                                                       uint8_t databits, \r
-                                                       uart_parity_t parity, \r
-                                                       uint8_t stopbits, \r
-                                                       bool flow_cntl) {\r
-    uint32_t uiDivisor;\r
-    uint32_t valLCR = 0;\r
-    uint32_t valMCR = MCR_OUT2;\r
-      \r
-    uiDivisor = 921600/baudrate;\r
-    // Check for invalid baud rate divisor value.\r
-    // XXX - Eventually could use '0' to imply auto rate detection\r
-    if ((uiDivisor & 0xFFFF0000) || (uiDivisor == 0)) {\r
-      return EINVAL;\r
-    }\r
-\r
-    if ((databits > 8 || databits < 5)) {\r
-      return EINVAL;\r
-    }\r
-    valLCR |= LCR_WLS((databits-5));\r
-\r
-    switch (parity) {\r
-    case EVEN: \r
-      valLCR |= LCR_EPS;\r
-      // Fall through to enable\r
-    case ODD:\r
-      valLCR |= LCR_PEN;\r
-      break;\r
-    case NONE:\r
-      break;\r
-    default:\r
-      return EINVAL;\r
-      break;\r
-    }\r
-    \r
-    if ((stopbits > 2) || (stopbits < 1)) {\r
-      return EINVAL;\r
-    }\r
-    else if (stopbits == 2) {\r
-      valLCR |= LCR_STB;\r
-    }\r
-\r
-    if (flow_cntl) {\r
-      valMCR |= MCR_AFE;\r
-    }\r
-\r
-    atomic {\r
-      call UART.setDLL((uiDivisor & 0xFF));\r
-      call UART.setDLH(((uiDivisor >> 8) & 0xFF));\r
-      call UART.setLCR(valLCR);\r
-      call UART.setMCR(valMCR);\r
-    }\r
\r
-    return SUCCESS;\r
-  }\r
-    \r
-  async command error_t HalPXA27xSerialCntl.flushPort() {\r
-\r
-    atomic {\r
-      call UART.setFCR(gulFCRShadow | FCR_RESETTF | FCR_RESETRF);\r
-    }\r
-\r
-    return SUCCESS;\r
-  }\r
-  \r
-  async event void UART.interruptUART() {\r
-    uint8_t error, intSource;\r
-    uint8_t ucByte;\r
-\r
-    intSource = call UART.getIIR();\r
-    intSource &= IIR_IID_MASK;\r
-    intSource = intSource >> 1;\r
-    \r
-    switch (intSource) {\r
-    case 0: // MODEM STATUS\r
-      break;\r
-    case 1: // TRANSMIT FIFO\r
-      call UART.setIER(call UART.getIER() & ~IER_TIE);\r
-      DispatchStreamSendSignal();\r
-      break;\r
-    case 2: // RECEIVE FIFO data available\r
-      while (call UART.getLSR() & LSR_DR) {\r
-       ucByte = call UART.getRBR();\r
-\r
-       if (rxCurrentBuf != NULL) {\r
-         rxCurrentBuf[rxCurrentIdx] = ucByte;\r
-         rxCurrentIdx++;\r
-         if (rxCurrentIdx >= rxCurrentLen) \r
-           DispatchStreamRcvSignal();\r
-       }\r
-       else if (gbRcvByteEvtEnabled) {\r
-         signal UartStream.receivedByte(ucByte);\r
-       }\r
-      }\r
-      break;\r
-    case 3: // ERROR\r
-      error = call UART.getLSR();\r
-      break;\r
-    default:\r
-      break;\r
-    }\r
-    return;\r
-  }\r
-\r
-  default async event void UartStream.sendDone( uint8_t* buf, uint16_t len, error_t error ) {\r
-    return; \r
-  }\r
-\r
-  default async event void UartStream.receivedByte(uint8_t data) {\r
-    return;\r
-  }\r
-\r
-  default async event void UartStream.receiveDone( uint8_t* buf, uint16_t len, error_t error ) {\r
-    return;\r
-  }\r
-\r
-  default async event uint8_t* HalPXA27xSerialPacket.sendDone(uint8_t *buf, \r
-                                                             uint16_t len, \r
-                                                             uart_status_t status) {\r
-    return NULL;\r
-  }\r
-\r
-  default async event uint8_t* HalPXA27xSerialPacket.receiveDone(uint8_t *buf, \r
-                                                                uint16_t len, \r
-                                                                uart_status_t status) {\r
-    return NULL;\r
-  }\r
-\r
-\r
-}\r
+/* $Id$ */
+/*
+ * Copyright (c) 2005 Arched Rock Corporation 
+ * All rights reserved. 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *  
+ *   Neither the name of the Arched Rock Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ARCHED
+ * ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+/*
+ *  Intel Open Source License
+ *
+ *  Copyright (c) 2002 Intel Corporation
+ *  All rights reserved.
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *     Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *      Neither the name of the Intel Corporation nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+/**
+ * Implements the UartByte, UartStream and HalPXA27xSerialPacket interface 
+ * for a PXA27x UART. 
+ * 
+ *
+ * @param defaultRate Default baud rate for the serial port. 
+ *
+ *
+ * @author Phil Buonadonna
+ */
+
+#include "pxa27x_serial.h"
+
+generic module HalPXA27xSerialP(uint32_t defaultRate)
+{
+  provides {
+    interface Init;
+    interface StdControl;
+    interface UartByte;
+    interface UartStream;
+    interface HalPXA27xSerialPacket;
+    interface HalPXA27xSerialCntl;
+  }
+  uses {
+    interface Init as UARTInit;
+    interface HplPXA27xUART as UART;
+    interface HplPXA27xDMAChnl as RxDMA;
+    interface HplPXA27xDMAChnl as TxDMA;
+    interface HplPXA27xDMAInfo as UARTRxDMAInfo;
+    interface HplPXA27xDMAInfo as UARTTxDMAInfo;
+  }
+}
+
+implementation 
+{
+
+  uint8_t *txCurrentBuf, *rxCurrentBuf;
+  uint32_t txCurrentLen, rxCurrentLen, rxCurrentIdx;
+  uint32_t gulFCRShadow;
+  bool gbUsingUartStreamSendIF = FALSE;
+  bool gbUsingUartStreamRcvIF = FALSE;
+  bool gbRcvByteEvtEnabled = TRUE;
+
+  command error_t Init.init() {
+    error_t error = SUCCESS;
+
+    atomic {
+      call UARTInit.init();
+      txCurrentBuf = rxCurrentBuf = NULL;
+      gbUsingUartStreamSendIF = FALSE;
+      gbUsingUartStreamRcvIF = FALSE;
+      gbRcvByteEvtEnabled = TRUE;
+      gulFCRShadow = (FCR_TRFIFOE | FCR_ITL(0)); // FIFO Mode, 1 byte Rx threshold
+    }
+    call TxDMA.setMap(call UARTTxDMAInfo.getMapIndex());
+    call RxDMA.setMap(call UARTRxDMAInfo.getMapIndex());
+    call TxDMA.setDALGNbit(TRUE);
+    call RxDMA.setDALGNbit(TRUE);
+
+    error = call HalPXA27xSerialCntl.configPort(defaultRate,8,NONE,1,FALSE);
+    
+    atomic {call UART.setFCR(gulFCRShadow);}
+    return error;
+  }
+
+  command error_t StdControl.start() {
+    atomic {
+      call UART.setIER(IER_UUE | IER_RAVIE);
+    }
+    return SUCCESS;
+  }
+
+  command error_t StdControl.stop() {
+    atomic {
+      call UART.setIER(0);
+    }
+    return SUCCESS;
+  }
+
+  async command error_t UartByte.send(uint8_t data) {
+    atomic call UART.setTHR(data);
+    while ((call UART.getLSR() & LSR_TEMT) == 0);
+    return SUCCESS;
+  }
+
+  async command error_t UartByte.receive( uint8_t *data, uint8_t timeout) {
+    error_t error = FAIL;
+    uint8_t t;
+    for (t = 0; t < timeout; t++) {
+      if (call UART.getLSR() & LSR_DR) {
+       *data = call UART.getRBR();
+       error = SUCCESS;
+       break;
+      }
+    }
+    return error;
+  }
+
+  async command error_t UartStream.send( uint8_t* buf, uint16_t len ) {
+    error_t error;
+    atomic gbUsingUartStreamSendIF = TRUE;
+    error = call HalPXA27xSerialPacket.send(buf,len);
+    if (error) {
+      atomic gbUsingUartStreamSendIF = FALSE;
+    }
+    return error;
+  }
+
+
+  async command error_t UartStream.enableReceiveInterrupt() {
+    error_t error = SUCCESS;
+    atomic {
+      if (rxCurrentBuf == NULL) {
+       call UART.setIER(call UART.getIER() | IER_RAVIE);
+      }
+      gbRcvByteEvtEnabled = TRUE;
+    }
+    return SUCCESS;
+  }
+
+  async command error_t UartStream.disableReceiveInterrupt() {
+    atomic {
+      // Check to make sure a short stream/packet call isn't in progress
+      if ((rxCurrentBuf == NULL) || (rxCurrentLen >= 8)) {
+       call UART.setIER(call UART.getIER() & ~IER_RAVIE);
+      }
+      gbRcvByteEvtEnabled = FALSE;
+    }
+    return SUCCESS;
+  }
+
+  async command error_t UartStream.receive( uint8_t* buf, uint16_t len ) {
+    error_t error;
+    atomic gbUsingUartStreamRcvIF = TRUE;
+    error = call HalPXA27xSerialPacket.receive(buf,len,0);
+    if (error) {
+      atomic gbUsingUartStreamRcvIF = FALSE;
+    }
+    return error;
+  }
+  
+  async command error_t HalPXA27xSerialPacket.send(uint8_t *buf, uint16_t len) {
+    uint32_t txAddr;
+    uint32_t DMAFlags;
+    error_t error = SUCCESS;
+
+    atomic {
+      if (txCurrentBuf == NULL) {
+       txCurrentBuf = buf;
+       txCurrentLen = len;
+      }
+      else {
+       error = FAIL;
+      }
+    }
+
+    if (error) 
+      return error;
+    
+    if (len < 8) {
+      uint16_t i;
+      // Use PIO. Invariant: FIFO is empty
+      atomic {
+       gulFCRShadow |= FCR_TIL;
+       call UART.setFCR(gulFCRShadow); 
+      }
+      for (i = 0;i < len;i++) {
+       call UART.setTHR(buf[i]);
+      }
+      atomic call UART.setIER(call UART.getIER() | IER_TIE);
+    }
+    else {
+      // Use DMA
+      DMAFlags = (DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | DCMD_ENDIRQEN
+                 | DCMD_LEN(len) );
+      
+      txAddr = (uint32_t) buf;
+      DMAFlags |= DCMD_INCSRCADDR;
+      
+      call TxDMA.setDCSR(DCSR_NODESCFETCH);
+      call TxDMA.setDSADR(txAddr);
+      call TxDMA.setDTADR(call UARTTxDMAInfo.getAddr());
+      call TxDMA.setDCMD(DMAFlags);
+      
+      atomic {
+       call UART.setIER(call UART.getIER() | IER_DMAE);
+      }
+
+      call TxDMA.setDCSR(DCSR_RUN | DCSR_NODESCFETCH);
+    }
+    return error;
+  }
+
+
+  async command error_t HalPXA27xSerialPacket.receive(uint8_t *buf, uint16_t len, 
+                                                     uint16_t timeout) {
+    uint32_t rxAddr;
+    uint32_t DMAFlags;
+    error_t error = SUCCESS;
+
+    atomic {
+      if (rxCurrentBuf == NULL) {
+       rxCurrentBuf = buf;
+       rxCurrentLen = len;
+       rxCurrentIdx = 0;
+      }
+      else {
+       error = FAIL;
+      }
+    }
+
+    if (error) 
+      return error;
+
+    if (len < 8) {
+      // Use PIO. Invariant: FIFO is empty
+      atomic {
+       gulFCRShadow = ((gulFCRShadow & ~(FCR_ITL(3))) | FCR_ITL(0));
+       call UART.setFCR(gulFCRShadow); 
+       call UART.setIER(call UART.getIER() | IER_RAVIE);
+      }
+    }
+    else {
+      // Use DMA
+      DMAFlags = (DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | DCMD_ENDIRQEN
+                 | DCMD_LEN(len) );
+      
+      rxAddr = (uint32_t) buf;
+      DMAFlags |= DCMD_INCTRGADDR;
+      
+      call RxDMA.setDCSR(DCSR_NODESCFETCH);
+      call RxDMA.setDTADR(rxAddr);
+      call RxDMA.setDSADR(call UARTRxDMAInfo.getAddr());
+      call RxDMA.setDCMD(DMAFlags);
+
+      atomic {
+       gulFCRShadow = ((gulFCRShadow & ~(FCR_ITL(3))) | FCR_ITL(1));
+       call UART.setFCR(gulFCRShadow); 
+       call UART.setIER((call UART.getIER() & ~IER_RAVIE) | IER_DMAE);
+      }
+
+      call RxDMA.setDCSR(DCSR_RUN | DCSR_NODESCFETCH);
+    }
+    return error;
+  }
+  
+  void DispatchStreamRcvSignal() {
+    uint8_t *pBuf = rxCurrentBuf;
+    uint16_t len = rxCurrentLen;
+    rxCurrentBuf = NULL;
+    if (gbUsingUartStreamRcvIF) {
+      gbUsingUartStreamRcvIF = FALSE;
+      signal UartStream.receiveDone(pBuf, len, SUCCESS);
+    }
+    else {
+      pBuf = signal HalPXA27xSerialPacket.receiveDone(pBuf, len, SUCCESS);
+      if (pBuf) {
+       call HalPXA27xSerialPacket.receive(pBuf,len,0);
+      }
+    }
+    return;
+  }
+
+  void DispatchStreamSendSignal() {
+    uint8_t *pBuf = txCurrentBuf;
+    uint16_t len = txCurrentLen;
+    txCurrentBuf = NULL;
+    if (gbUsingUartStreamSendIF) {
+      gbUsingUartStreamSendIF = FALSE;
+      signal UartStream.sendDone(pBuf, len, SUCCESS);
+    }
+    else {
+      pBuf = signal HalPXA27xSerialPacket.sendDone(pBuf, len, SUCCESS);
+      if (pBuf) {
+       call HalPXA27xSerialPacket.send(pBuf,len);
+      }
+    }
+    return;
+  }
+
+  async event void RxDMA.interruptDMA() {
+    call RxDMA.setDCMD(0);
+    call RxDMA.setDCSR(DCSR_EORINT | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERRINTR);
+    DispatchStreamRcvSignal();
+    if (gbRcvByteEvtEnabled) 
+      call UART.setIER(call UART.getIER() | IER_RAVIE);
+    return;
+  }
+
+  async event void TxDMA.interruptDMA() {
+    call TxDMA.setDCMD(0);
+    call TxDMA.setDCSR(DCSR_EORINT | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERRINTR);
+    DispatchStreamSendSignal();
+    return;
+  }
+
+
+  async command error_t HalPXA27xSerialCntl.configPort(uint32_t baudrate, 
+                                                       uint8_t databits, 
+                                                       uart_parity_t parity, 
+                                                       uint8_t stopbits, 
+                                                       bool flow_cntl) {
+    uint32_t uiDivisor;
+    uint32_t valLCR = 0;
+    uint32_t valMCR = MCR_OUT2;
+      
+    uiDivisor = 921600/baudrate;
+    // Check for invalid baud rate divisor value.
+    // XXX - Eventually could use '0' to imply auto rate detection
+    if ((uiDivisor & 0xFFFF0000) || (uiDivisor == 0)) {
+      return EINVAL;
+    }
+
+    if ((databits > 8 || databits < 5)) {
+      return EINVAL;
+    }
+    valLCR |= LCR_WLS((databits-5));
+
+    switch (parity) {
+    case EVEN: 
+      valLCR |= LCR_EPS;
+      // Fall through to enable
+    case ODD:
+      valLCR |= LCR_PEN;
+      break;
+    case NONE:
+      break;
+    default:
+      return EINVAL;
+      break;
+    }
+    
+    if ((stopbits > 2) || (stopbits < 1)) {
+      return EINVAL;
+    }
+    else if (stopbits == 2) {
+      valLCR |= LCR_STB;
+    }
+
+    if (flow_cntl) {
+      valMCR |= MCR_AFE;
+    }
+
+    atomic {
+      call UART.setDLL((uiDivisor & 0xFF));
+      call UART.setDLH(((uiDivisor >> 8) & 0xFF));
+      call UART.setLCR(valLCR);
+      call UART.setMCR(valMCR);
+    }
+    return SUCCESS;
+  }
+    
+  async command error_t HalPXA27xSerialCntl.flushPort() {
+
+    atomic {
+      call UART.setFCR(gulFCRShadow | FCR_RESETTF | FCR_RESETRF);
+    }
+
+    return SUCCESS;
+  }
+  
+  async event void UART.interruptUART() {
+    uint8_t error, intSource;
+    uint8_t ucByte;
+
+    intSource = call UART.getIIR();
+    intSource &= IIR_IID_MASK;
+    intSource = intSource >> 1;
+    
+    switch (intSource) {
+    case 0: // MODEM STATUS
+      break;
+    case 1: // TRANSMIT FIFO
+      call UART.setIER(call UART.getIER() & ~IER_TIE);
+      DispatchStreamSendSignal();
+      break;
+    case 2: // RECEIVE FIFO data available
+      while (call UART.getLSR() & LSR_DR) {
+       ucByte = call UART.getRBR();
+
+       if (rxCurrentBuf != NULL) {
+         rxCurrentBuf[rxCurrentIdx] = ucByte;
+         rxCurrentIdx++;
+         if (rxCurrentIdx >= rxCurrentLen) 
+           DispatchStreamRcvSignal();
+       }
+       else if (gbRcvByteEvtEnabled) {
+         signal UartStream.receivedByte(ucByte);
+       }
+      }
+      break;
+    case 3: // ERROR
+      error = call UART.getLSR();
+      break;
+    default:
+      break;
+    }
+    return;
+  }
+
+  default async event void UartStream.sendDone( uint8_t* buf, uint16_t len, error_t error ) {
+    return; 
+  }
+
+  default async event void UartStream.receivedByte(uint8_t data) {
+    return;
+  }
+
+  default async event void UartStream.receiveDone( uint8_t* buf, uint16_t len, error_t error ) {
+    return;
+  }
+
+  default async event uint8_t* HalPXA27xSerialPacket.sendDone(uint8_t *buf, 
+                                                             uint16_t len, 
+                                                             uart_status_t status) {
+    return NULL;
+  }
+
+  default async event uint8_t* HalPXA27xSerialPacket.receiveDone(uint8_t *buf, 
+                                                                uint16_t len, 
+                                                                uart_status_t status) {
+    return NULL;
+  }
+
+
+}