📄 intr.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include "externs.h"/* * Process data in a line status register */static intprocess_lsr(DEV_8250 *dev, unsigned char lsr) { unsigned key = 0, eventflag = 0; // Return immediately if no errors. if((lsr & (LSR_BI|LSR_OE|LSR_FE|LSR_PE)) == 0) { /* No break, can re-enable the LSR interrupt. */ write_8250(dev->port[REG_IE], 0x0f); return(0); } // Save the error as out-of-band data which can be retrieved via devctl(). dev->tty.oband_data |= (lsr >> 1) & 0x0f; atomic_set(&dev->tty.flags, OBAND_DATA);// Uncomment for post 1.0 since there was no time to test sufficiently// if(dev->tty.notify[2].cnt) {// dev->tty.notify[2].cnt = 0; // Disarm// dev->tty.notify[2].event.sigev_value.sival_int |= _NOTIFY_COND_OBAND;// atomic_set(&dev->tty.flags, EVENT_NOTIFY_OBAND);// eventflag = 1;// } // Read whatever input data happens to be in the buffer to "eat" the // spurious data associated with break, parity error, etc. key = read_8250(dev->port[REG_RX]); if(lsr & LSR_BI) { key |= TTI_BREAK; /* On the MPC8540 chip, when a break occurs, the lsr interrupt stays asserted until a character is input. We therefore need to disable the lsr interrupt to prevent an interrupt overflow condition. */ write_8250(dev->port[REG_IE], 0x0b); } else { /* No break, can re-enable the LSR interrupt. */ write_8250(dev->port[REG_IE], 0x0f); if(lsr & LSR_OE) key |= TTI_OVERRUN; else if(lsr & LSR_FE) key |= TTI_FRAME; else if(lsr & LSR_PE) key |= TTI_PARITY; } return(tti(&dev->tty, key) | eventflag);}/* * Serial interrupt handler */const struct sigevent *ser_intr(void *area, int id) { struct dev_list *list = area; int status = 0; int something_happened; unsigned char msr, lsr; DEV_8250 *dev; struct sigevent *event = NULL; unsigned char fifo_counter; do { something_happened = 0; for(dev = list->device; dev != NULL; dev = dev->next) { unsigned iir; uintptr_t *port = dev->port; status = 0; iir = read_8250(port[REG_II]) & 0x07; switch(iir) { case II_RX: // Receive data do { status |= tti(&dev->tty, read_8250(port[REG_RX])); lsr = read_8250(port[REG_LS]); status |= process_lsr(dev, lsr); } while(lsr & LSR_RXRDY); break; case II_TX: // Transmit buffer empty fifo_counter = 0; do { dev->tty.un.s.tx_tmr = 0; // The override causes tto to ignore the check on tx buffer empty // since we know that the entire fifo is empty when the interrupt fires //status |= tto(&dev->tty, TTO_DATA, dev->fifo_override); status |= tto(&dev->tty, TTO_DATA, FIFO_XMIT_OVERRIDE); } while( (++fifo_counter < dev->tx_fifo) && (dev->tty.obuf.cnt > 0) ); break; case II_MS: // Modem change msr = read_8250(port[REG_MS]); if(msr & MSR_DDCD) status |= tti(&dev->tty, (msr & MSR_DCD) ? TTI_CARRIER : TTI_HANGUP); if((msr & MSR_DCTS) && (dev->tty.c_cflag & OHFLOW)) status |= tti(&dev->tty, (msr & MSR_CTS) ? TTI_OHW_CONT : TTI_OHW_STOP); break; case II_LS: // Line status change lsr = read_8250(port[REG_LS]); status |= process_lsr(dev, lsr); break; default: continue; } something_happened = 1; if(status) { if((dev->tty.flags & EVENT_QUEUED) == 0) { event = &ttyctrl.event; dev_lock(&ttyctrl); ttyctrl.event_queue[ttyctrl.num_events++] = &dev->tty; atomic_set(&dev->tty.flags, EVENT_QUEUED); dev_unlock(&ttyctrl); } } } } while(something_happened); return(event); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -