00001 00007 /* Embedded XINU, Copyright (C) 2007. All rights reserved. */ 00008 00009 #include <kernel.h> 00010 #include <device.h> 00011 #include <uart.h> 00012 #include <semaphore.h> 00013 00017 interrupt uartIntr(void) 00018 { 00019 short u = 0, iir = 0, lsr = 0, count = 0; 00020 char c; 00021 struct uart *puart = NULL; 00022 struct uart_csreg *pucsr = NULL; 00023 00024 for (u = 0; u < NUART; u++) 00025 { 00026 puart = &uarttab[u]; 00027 if (NULL == puart) { continue; } 00028 pucsr = puart->csr; 00029 if (NULL == pucsr) { continue; } 00030 00031 /* Check interrupt identification register */ 00032 iir = pucsr->iir; 00033 if (iir & UART_IIR_IRQ) { continue; } 00034 00035 /* 00036 * Decode interrupt cause based upon the value taken from the 00037 * UART interrupt identification register. Clear interrupt source, 00038 * and perform the appropriate handling to coordinate properly 00039 * with the upper half of the driver. 00040 */ 00041 00042 /* Decode interrupt cause */ 00043 iir &= UART_IIR_IDMASK; 00044 switch (iir) 00045 { 00046 /* Receiver line status interrupt */ 00047 case UART_IIR_RLSI: 00048 lsr = pucsr->lsr; 00049 puart->lserr++; 00050 break; 00051 00052 /* Receiver data available or timed out */ 00053 case UART_IIR_RDA: 00054 case UART_IIR_RTO: 00055 puart->iirq++; 00056 count = 0; 00057 while (pucsr->lsr & UART_LSR_DR) 00058 { 00059 c = pucsr->buffer; 00060 if (puart->icount < UART_IBLEN) 00061 { 00062 puart->in[(puart->istart+puart->icount) % UART_IBLEN] = c; 00063 puart->icount++; 00064 count++; 00065 } 00066 else 00067 { 00068 puart->ovrrn++; 00069 } 00070 } 00071 puart->cin += count; 00072 signaln(puart->isema, count); 00073 break; 00074 00075 /* Transmitter holding register empty */ 00076 case UART_IIR_THRE: 00077 puart->oirq++; 00078 lsr = pucsr->lsr; /*Read from LSR to clear interrupt */ 00079 count = 0; 00080 if (puart->ocount > 0) 00081 { 00082 do 00083 { 00084 count++; 00085 puart->ocount--; 00086 pucsr->buffer = puart->out[puart->ostart]; 00087 puart->ostart = (puart->ostart + 1) % UART_OBLEN; 00088 } while ((count < UART_FIFO_LEN) && (puart->ocount > 0)); 00089 } 00090 00091 if (count) 00092 { 00093 puart->cout += count; 00094 signaln(puart->osema, count); 00095 } 00096 else 00097 { 00098 puart->oidle = 1; 00099 } 00100 break; 00101 00102 /* Modem status change */ 00103 case UART_IIR_MSC: 00104 break; 00105 } 00106 } 00107 }