📄 tto.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"inttto(TTYDEV *ttydev, int action, int arg1) { TTYBUF *bup = &ttydev->obuf; DEV_8250 *dev = (DEV_8250 *)ttydev; const uintptr_t *port = dev->port; int status = 0; unsigned char c; switch(action) { case TTO_STTY: ser_stty(dev); return(0); case TTO_CTRL: if(arg1 & _SERCTL_BRK_CHG) set_port(port[REG_LC], LCR_BREAK, arg1 &_SERCTL_BRK ? LCR_BREAK : 0); if(arg1 & _SERCTL_DTR_CHG) set_port(port[REG_MC], MCR_DTR, arg1 & _SERCTL_DTR ? MCR_DTR : 0); if(arg1 & _SERCTL_RTS_CHG) set_port(port[REG_MC], MCR_RTS, arg1 & _SERCTL_RTS ? MCR_RTS : 0); return(0); case TTO_LINESTATUS: return(((read_8250(port[REG_MS]) << 8) | read_8250(port[REG_MC])) & 0xf003); case TTO_DATA: break; default: return(0); } /* * If the OSW_PAGED_OVERRIDE flag is set then allow * transmit of character even if output is suspended via * the OSW_PAGED flag. This flag implies that the next * character in the obuf is a software flow control * charater (STOP/START). * Note: tx_inject sets it up so that the contol * character is at the start (tail) of the buffer. * */ if(dev->tty.flags & (OHW_PAGED|OSW_PAGED) && !(dev->tty.xflags & OSW_PAGED_OVERRIDE)) return(0); dev_lock(&dev->tty); if(bup->cnt > 0) { if( (read_8250(port[REG_LS]) & LSR_TXRDY) || ( dev->tx_fifo > 0 && arg1 == FIFO_XMIT_OVERRIDE) ) { // Get the next character to print from the output buffer c = *bup->tail; if(c == '\n' && ((dev->tty.c_oflag & (OPOST | ONLCR)) == (OPOST | ONLCR)) && ((dev->tty.flags & NL_INSERT) == 0)) { c = '\r'; atomic_set(&dev->tty.flags, NL_INSERT); } else { atomic_clr(&dev->tty.flags, NL_INSERT); if(++bup->tail >= &bup->buff[bup->size]) bup->tail = &bup->buff[0]; --bup->cnt; } // Print the character dev->tty.un.s.tx_tmr = 3; /* Timeout */ write_8250(port[REG_TX], c); /* Clear the OSW_PAGED_OVERRIDE flag as we only want * one character to be transmitted in this case. */ if (dev->tty.xflags & OSW_PAGED_OVERRIDE) atomic_clr(&dev->tty.xflags, OSW_PAGED_OVERRIDE); } dev_unlock(&dev->tty); } else { dev_unlock(&dev->tty); // Check for notify conditions if(dev->tty.notify[1].cnt < bup->size - bup->cnt) { dev->tty.notify[1].cnt = (~0u) >> 1; // Disarm atomic_set(&dev->tty.flags, EVENT_NOTIFY_OUTPUT); status = 1; } // Is anyone waiting for the output buffer to drain? if(dev->tty.waiting_drain && bup->cnt == 0) { atomic_set(&dev->tty.flags, EVENT_DRAIN); status = 1; } } // If anyone is waiting to write, kick them when buffer drains to 1/4 full. if(dev->tty.waiting_write && bup->cnt < bup->size/4) { atomic_set(&dev->tty.flags, EVENT_WRITE); return(1); } return(status);}voidser_stty(DEV_8250 *dev) { unsigned lcr = 0; const uintptr_t *port = dev->port; unsigned value; // Set Baud rate value = (dev->tty.baud == 0) ? 0 : (dev->clk/(dev->tty.baud * dev->div)); dev_lock(&dev->tty); set_port(port[REG_LC], LCR_DLAB, LCR_DLAB); set_port(port[REG_DL0], 0xff, value & 0xff); set_port(port[REG_DL1], 0xff, value >> 8); set_port(port[REG_LC], LCR_DLAB, 0); dev_unlock(&dev->tty); // Set data bits switch(dev->tty.c_cflag & CSIZE) { case CS8: ++lcr; case CS7: ++lcr; case CS6: ++lcr; } // Set stop bits if(dev->tty.c_cflag & CSTOPB) lcr |= LCR_STB2; // Set parity bits if(dev->tty.c_cflag & PARENB) lcr |= LCR_PEN; if((dev->tty.c_cflag & PARODD) == 0) lcr |= LCR_EPS; set_port(port[REG_LC], 0xFF, lcr); // turn on DTR, RTS set_port(port[REG_MC], MCR_DTR|MCR_RTS, MCR_DTR|MCR_RTS); // Extract the rx and tx fifo sizes dev->rx_fifo = dev->tty.fifo & 0xf; dev->tx_fifo = (dev->tty.fifo >> 4) & 0xf; // Set RX fifo trigger level switch(dev->rx_fifo) { case 1: value = 0x01; break; case 4: value = 0x41; break; case 8: value = 0x81; break; case 14: value = 0xC1; break; default: value = 0x00; break; } // If only the TX fifo is set, enable the fifo and set RX trigger = 1 if(dev->tx_fifo && !value) { value = 0x01; } if(value) { // // Try to enable 1/4/8/14-deep FIFO mode if a 16550 // NOTE: That this is NOT always desirable since it significantly // affects received character timing, and does NOT // significantly increase receive performance. // (Keep in mind that the 16550 with FIFO disabled // is still very useful, since it SHOULD buffer // up to 16 received characters even when FIFO is off) // write_8250(port[REG_FC], value); if((read_8250(port[REG_II]) & II_FIFO) == 0) { // No FIFO, not an 16550 so reset FIFO write_8250(port[REG_FC], 0x00); } } else { write_8250(port[REG_FC], 0x00); //If no threshold specified, reset the fifo }}#if 0voidser_ctrl(DEV_8250 *dev, unsigned flags) { if(flags & _SERCTL_BRK_CHG) set_port(dev->port[REG_LC], LCR_BREAK, flags &_SERCTL_BRK ? LCR_BREAK : 0); if(flags & _SERCTL_DTR_CHG) set_port(dev->port[REG_MC], MCR_DTR, flags & _SERCTL_DTR ? MCR_DTR : 0); if(flags & _SERCTL_RTS_CHG) set_port(dev->port[REG_MC], MCR_RTS, flags & _SERCTL_RTS ? MCR_RTS : 0);}#endifint drain_check(TTYDEV *ttydev, uintptr_t *count) { TTYBUF *bup = &ttydev->obuf; DEV_8250 *dev = (DEV_8250 *)ttydev; const uintptr_t *port = dev->port; // if the device has DRAINED, return 1 if (dev->tty.waiting_drain && (bup->cnt == 0) && (read_8250(port[REG_LS]) & LSR_TSRE)) return 1; // if the device has not DRAINED, set a timer based on 50ms counts // wait for the time it takes for one character to be transmitted // out the shift register. We do this dynamically since the // baud rate can change. *count = ((IO_CHAR_DEFAULT_BITSIZE * 20) / ttydev->baud) + 1; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -