+
+/**
+ * Serial 0 TX interrupt handler
+ */
+static void uart0_irq_tx(void)
+{
+ SER_STROBE_ON;
+
+ struct FIFOBuffer * const txfifo = &ser_uart0->txfifo;
+
+ if (fifo_isempty(txfifo))
+ {
+ /*
+ * - Disable the TX empty interrupts
+ */
+ US0_IDR = BV(US_TXEMPTY);
+ SER_UART0_BUS_TXEND;
+ UARTDescs[SER_UART0].sending = false;
+ }
+ else
+ {
+ char c = fifo_pop(txfifo);
+ SER_UART0_BUS_TXCHAR(c);
+ }
+
+ SER_STROBE_OFF;
+}
+
+/**
+ * Serial 0 RX complete interrupt handler.
+ */
+static void uart0_irq_rx(void)
+{
+ SER_STROBE_ON;
+
+ /* Should be read before US_CRS */
+ ser_uart0->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
+
+ char c = US0_RHR;
+ struct FIFOBuffer * const rxfifo = &ser_uart0->rxfifo;
+
+ if (fifo_isfull(rxfifo))
+ ser_uart0->status |= SERRF_RXFIFOOVERRUN;
+ else
+ fifo_push(rxfifo, c);
+
+ SER_STROBE_OFF;
+}
+
+/**
+ * Serial IRQ dispatcher for USART0.
+ */
+static void uart0_irq_dispatcher(void) __attribute__ ((interrupt));
+static void uart0_irq_dispatcher(void)
+{
+ if (US0_CSR & BV(US_RXRDY))
+ uart0_irq_rx();
+
+ if (US0_CSR & BV(US_TXEMPTY))
+ uart0_irq_tx();
+
+ /* Inform hw that we have served the IRQ */
+ AIC_EOICR = 0;
+}
+
+/**
+ * Serial 1 TX interrupt handler
+ */
+static void uart1_irq_tx(void)
+{
+ SER_STROBE_ON;
+
+ struct FIFOBuffer * const txfifo = &ser_uart1->txfifo;
+
+ if (fifo_isempty(txfifo))
+ {
+ /*
+ * - Disable the TX empty interrupts
+ */
+ US1_IDR = BV(US_TXEMPTY);
+ SER_UART1_BUS_TXEND;
+ UARTDescs[SER_UART1].sending = false;
+ }
+ else
+ {
+ char c = fifo_pop(txfifo);
+ SER_UART1_BUS_TXCHAR(c);
+ }
+
+ SER_STROBE_OFF;
+}
+
+/**
+ * Serial 1 RX complete interrupt handler.
+ */
+static void uart1_irq_rx(void)
+{
+ SER_STROBE_ON;
+
+ /* Should be read before US_CRS */
+ ser_uart1->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
+
+ char c = US1_RHR;
+ struct FIFOBuffer * const rxfifo = &ser_uart1->rxfifo;
+
+ if (fifo_isfull(rxfifo))
+ ser_uart1->status |= SERRF_RXFIFOOVERRUN;
+ else
+ fifo_push(rxfifo, c);
+
+ SER_STROBE_OFF;
+}
+
+/**
+ * Serial IRQ dispatcher for USART1.
+ */
+static void uart1_irq_dispatcher(void) __attribute__ ((interrupt));
+static void uart1_irq_dispatcher(void)
+{
+ if (US1_CSR & BV(US_RXRDY))
+ uart1_irq_rx();
+
+ if (US1_CSR & BV(US_TXEMPTY))
+ uart1_irq_tx();
+
+ /* Inform hw that we have served the IRQ */
+ AIC_EOICR = 0;
+}
+
+/**
+ * SPI0 interrupt handler
+ */
+static void spi0_irq_handler(void) __attribute__ ((interrupt));
+static void spi0_irq_handler(void)
+{
+ SER_STROBE_ON;
+
+ char c = SPI0_RDR;
+ /* Read incoming byte. */
+ if (!fifo_isfull(&ser_spi0->rxfifo))
+ fifo_push(&ser_spi0->rxfifo, c);
+ /*
+ * FIXME
+ else
+ ser_spi0->status |= SERRF_RXFIFOOVERRUN;
+ */
+
+ /* Send */
+ if (!fifo_isempty(&ser_spi0->txfifo))
+ SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
+ else
+ UARTDescs[SER_SPI0].sending = false;
+
+ /* Inform hw that we have served the IRQ */
+ AIC_EOICR = 0;
+ SER_STROBE_OFF;
+}
+
+
+#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X128
+/**
+ * SPI1 interrupt handler
+ */
+static void spi1_irq_handler(void) __attribute__ ((interrupt));
+static void spi1_irq_handler(void)
+{
+ SER_STROBE_ON;
+
+ char c = SPI1_RDR;
+ /* Read incoming byte. */
+ if (!fifo_isfull(&ser_spi1->rxfifo))
+ fifo_push(&ser_spi1->rxfifo, c);
+ /*
+ * FIXME
+ else
+ ser_spi1->status |= SERRF_RXFIFOOVERRUN;
+ */
+
+ /* Send */
+ if (!fifo_isempty(&ser_spi1->txfifo))
+ SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
+ else
+ UARTDescs[SER_SPI1].sending = false;
+
+ /* Inform hw that we have served the IRQ */
+ AIC_EOICR = 0;
+ SER_STROBE_OFF;
+}
+#endif