cregit-Linux how code gets into the kernel

Release 4.7 drivers/tty/serial/jsm/jsm_tty.c

/************************************************************************
 * Copyright 2003 Digi International (www.digi.com)
 *
 * Copyright (C) 2004 IBM Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * Contact Information:
 * Scott H Kilau <Scott_Kilau@digi.com>
 * Ananda Venkatarman <mansarov@us.ibm.com>
 * Modifications:
 * 01/19/06:    changed jsm_input routine to use the dynamically allocated
 *              tty_buffer changes. Contributors: Scott Kilau and Ananda V.
 ***********************************************************************/
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/delay.h>	/* For udelay */
#include <linux/pci.h>
#include <linux/slab.h>

#include "jsm.h"

static DECLARE_BITMAP(linemap, MAXLINES);

static void jsm_carrier(struct jsm_channel *ch);


static inline int jsm_get_mstat(struct jsm_channel *ch) { unsigned char mstat; unsigned result; jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "start\n"); mstat = (ch->ch_mostat | ch->ch_mistat); result = 0; if (mstat & UART_MCR_DTR) result |= TIOCM_DTR; if (mstat & UART_MCR_RTS) result |= TIOCM_RTS; if (mstat & UART_MSR_CTS) result |= TIOCM_CTS; if (mstat & UART_MSR_DSR) result |= TIOCM_DSR; if (mstat & UART_MSR_RI) result |= TIOCM_RI; if (mstat & UART_MSR_DCD) result |= TIOCM_CD; jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n"); return result; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong12498.41%150.00%
joe perchesjoe perches21.59%150.00%
Total126100.00%2100.00%


static unsigned int jsm_tty_tx_empty(struct uart_port *port) { return TIOCSER_TEMT; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong15100.00%1100.00%
Total15100.00%1100.00%

/* * Return modem signals to ld. */
static unsigned int jsm_tty_get_mctrl(struct uart_port *port) { int result; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n"); result = jsm_get_mstat(channel); if (result < 0) return -ENXIO; jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n"); return result; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong6988.46%133.33%
fabian frederickfabian frederick78.97%133.33%
joe perchesjoe perches22.56%133.33%
Total78100.00%3100.00%

/* * jsm_set_modem_info() * * Set modem signals, called by ld. */
static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n"); if (mctrl & TIOCM_RTS) channel->ch_mostat |= UART_MCR_RTS; else channel->ch_mostat &= ~UART_MCR_RTS; if (mctrl & TIOCM_DTR) channel->ch_mostat |= UART_MCR_DTR; else channel->ch_mostat &= ~UART_MCR_DTR; channel->ch_bd->bd_ops->assert_modem_signals(channel); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n"); udelay(10); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong10592.11%133.33%
fabian frederickfabian frederick76.14%133.33%
joe perchesjoe perches21.75%133.33%
Total114100.00%3100.00%

/* * jsm_tty_write() * * Take data from the user or kernel and send it out to the FEP. * In here exists all the Transparent Print magic as well. */
static void jsm_tty_write(struct uart_port *port) { struct jsm_channel *channel; channel = container_of(port, struct jsm_channel, uart_port); channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel); }

Contributors

PersonTokensPropCommitsCommitProp
thadeu lima de souza cascardothadeu lima de souza cascardo39100.00%1100.00%
Total39100.00%1100.00%


static void jsm_tty_start_tx(struct uart_port *port) { struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n"); channel->ch_flags &= ~(CH_STOP); jsm_tty_write(port); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n"); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong5986.76%133.33%
fabian frederickfabian frederick710.29%133.33%
joe perchesjoe perches22.94%133.33%
Total68100.00%3100.00%


static void jsm_tty_stop_tx(struct uart_port *port) { struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n"); channel->ch_flags |= (CH_STOP); jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n"); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong5385.48%133.33%
fabian frederickfabian frederick711.29%133.33%
joe perchesjoe perches23.23%133.33%
Total62100.00%3100.00%


static void jsm_tty_send_xchar(struct uart_port *port, char ch) { unsigned long lock_flags; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); termios = &port->state->port.tty->termios; if (ch == termios->c_cc[VSTART]) channel->ch_bd->bd_ops->send_start_character(channel); if (ch == termios->c_cc[VSTOP]) channel->ch_bd->bd_ops->send_stop_character(channel); spin_unlock_irqrestore(&port->lock, lock_flags); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong9179.13%114.29%
jesper juhljesper juhl1210.43%114.29%
fabian frederickfabian frederick76.09%114.29%
alan coxalan cox54.35%457.14%
Total115100.00%7100.00%


static void jsm_tty_stop_rx(struct uart_port *port) { struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); channel->ch_bd->bd_ops->disable_receiver(channel); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong3081.08%150.00%
fabian frederickfabian frederick718.92%150.00%
Total37100.00%2100.00%


static void jsm_tty_break(struct uart_port *port, int break_state) { unsigned long lock_flags; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); spin_lock_irqsave(&port->lock, lock_flags); if (break_state == -1) channel->ch_bd->bd_ops->send_break(channel); else channel->ch_bd->bd_ops->clear_break(channel); spin_unlock_irqrestore(&port->lock, lock_flags); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong7691.57%150.00%
fabian frederickfabian frederick78.43%150.00%
Total83100.00%2100.00%


static int jsm_tty_open(struct uart_port *port) { struct jsm_board *brd; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); struct ktermios *termios; /* Get board pointer from our array of majors we have allocated */ brd = channel->ch_bd; /* * Allocate channel buffers for read/write/error. * Set flag, so we don't get trounced on. */ channel->ch_flags |= (CH_OPENING); /* Drop locks, as malloc with GFP_KERNEL can sleep */ if (!channel->ch_rqueue) { channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL); if (!channel->ch_rqueue) { jsm_dbg(INIT, &channel->ch_bd->pci_dev, "unable to allocate read queue buf\n"); return -ENOMEM; } } if (!channel->ch_equeue) { channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL); if (!channel->ch_equeue) { jsm_dbg(INIT, &channel->ch_bd->pci_dev, "unable to allocate error queue buf\n"); return -ENOMEM; } } channel->ch_flags &= ~(CH_OPENING); /* * Initialize if neither terminal is open. */ jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "jsm_open: initializing channel in open...\n"); /* * Flush input queues. */ channel->ch_r_head = channel->ch_r_tail = 0; channel->ch_e_head = channel->ch_e_tail = 0; brd->bd_ops->flush_uart_write(channel); brd->bd_ops->flush_uart_read(channel); channel->ch_flags = 0; channel->ch_cached_lsr = 0; channel->ch_stops_sent = 0; termios = &port->state->port.tty->termios; channel->ch_c_cflag = termios->c_cflag; channel->ch_c_iflag = termios->c_iflag; channel->ch_c_oflag = termios->c_oflag; channel->ch_c_lflag = termios->c_lflag; channel->ch_startc = termios->c_cc[VSTART]; channel->ch_stopc = termios->c_cc[VSTOP]; /* Tell UART to init itself */ brd->bd_ops->uart_init(channel); /* * Run param in case we changed anything */ brd->bd_ops->param(channel); jsm_carrier(channel); channel->ch_open_count++; jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong31090.64%110.00%
jesper juhljesper juhl113.22%110.00%
fabian frederickfabian frederick72.05%110.00%
joe perchesjoe perches61.75%110.00%
alan coxalan cox51.46%440.00%
burman yanburman yan20.58%110.00%
breno leitaobreno leitao10.29%110.00%
Total342100.00%10100.00%


static void jsm_tty_close(struct uart_port *port) { struct jsm_board *bd; struct ktermios *ts; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "start\n"); bd = channel->ch_bd; ts = &port->state->port.tty->termios; channel->ch_flags &= ~(CH_STOPI); channel->ch_open_count--; /* * If we have HUPCL set, lower DTR and RTS */ if (channel->ch_c_cflag & HUPCL) { jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "Close. HUPCL set, dropping DTR/RTS\n"); /* Drop RTS/DTR */ channel->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS); bd->bd_ops->assert_modem_signals(channel); } /* Turn off UART interrupts for this port */ channel->ch_bd->bd_ops->uart_off(channel); jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "finish\n"); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong13989.68%112.50%
fabian frederickfabian frederick74.52%112.50%
alan coxalan cox63.87%562.50%
joe perchesjoe perches31.94%112.50%
Total155100.00%8100.00%


static void jsm_tty_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old_termios) { unsigned long lock_flags; struct jsm_channel *channel = container_of(port, struct jsm_channel, uart_port); spin_lock_irqsave(&port->lock, lock_flags); channel->ch_c_cflag = termios->c_cflag; channel->ch_c_iflag = termios->c_iflag; channel->ch_c_oflag = termios->c_oflag; channel->ch_c_lflag = termios->c_lflag; channel->ch_startc = termios->c_cc[VSTART]; channel->ch_stopc = termios->c_cc[VSTOP]; channel->ch_bd->bd_ops->param(channel); jsm_carrier(channel); spin_unlock_irqrestore(&port->lock, lock_flags); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong12193.08%133.33%
fabian frederickfabian frederick75.38%133.33%
alan coxalan cox21.54%133.33%
Total130100.00%3100.00%


static const char *jsm_tty_type(struct uart_port *port) { return "jsm"; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong16100.00%1100.00%
Total16100.00%1100.00%


static void jsm_tty_release_port(struct uart_port *port) { }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong10100.00%1100.00%
Total10100.00%1100.00%


static int jsm_tty_request_port(struct uart_port *port) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong14100.00%1100.00%
Total14100.00%1100.00%


static void jsm_config_port(struct uart_port *port, int flags) { port->type = PORT_JSM; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong20100.00%1100.00%
Total20100.00%1100.00%

static struct uart_ops jsm_ops = { .tx_empty = jsm_tty_tx_empty, .set_mctrl = jsm_tty_set_mctrl, .get_mctrl = jsm_tty_get_mctrl, .stop_tx = jsm_tty_stop_tx, .start_tx = jsm_tty_start_tx, .send_xchar = jsm_tty_send_xchar, .stop_rx = jsm_tty_stop_rx, .break_ctl = jsm_tty_break, .startup = jsm_tty_open, .shutdown = jsm_tty_close, .set_termios = jsm_tty_set_termios, .type = jsm_tty_type, .release_port = jsm_tty_release_port, .request_port = jsm_tty_request_port, .config_port = jsm_config_port, }; /* * jsm_tty_init() * * Init the tty subsystem. Called once per board after board has been * downloaded and init'ed. */
int jsm_tty_init(struct jsm_board *brd) { int i; void __iomem *vaddr; struct jsm_channel *ch; if (!brd) return -ENXIO; jsm_dbg(INIT, &brd->pci_dev, "start\n"); /* * Initialize board structure elements. */ brd->nasync = brd->maxports; /* * Allocate channel memory that might not have been allocated * when the driver was first loaded. */ for (i = 0; i < brd->nasync; i++) { if (!brd->channels[i]) { /* * Okay to malloc with GFP_KERNEL, we are not at * interrupt context, and there are no locks held. */ brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL); if (!brd->channels[i]) { jsm_dbg(CORE, &brd->pci_dev, "%s:%d Unable to allocate memory for channel struct\n", __FILE__, __LINE__); } } } ch = brd->channels[0]; vaddr = brd->re_map_membase; /* Set up channel variables */ for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) { if (!brd->channels[i]) continue; spin_lock_init(&ch->ch_lock); if (brd->bd_uart_offset == 0x200) ch->ch_neo_uart = vaddr + (brd->bd_uart_offset * i); else ch->ch_cls_uart = vaddr + (brd->bd_uart_offset * i); ch->ch_bd = brd; ch->ch_portnum = i; /* .25 second delay */ ch->ch_close_delay = 250; init_waitqueue_head(&ch->ch_flags_wait); } jsm_dbg(INIT, &brd->pci_dev, "finish\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong24992.22%120.00%
konrad zapalowiczkonrad zapalowicz155.56%120.00%
joe perchesjoe perches31.11%120.00%
al viroal viro20.74%120.00%
burman yanburman yan10.37%120.00%
Total270100.00%5100.00%


int jsm_uart_port_init(struct jsm_board *brd) { int i, rc; unsigned int line; struct jsm_channel *ch; if (!brd) return -ENXIO; jsm_dbg(INIT, &brd->pci_dev, "start\n"); /* * Initialize board structure elements. */ brd->nasync = brd->maxports; /* Set up channel variables */ for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) { if (!brd->channels[i]) continue; brd->channels[i]->uart_port.irq = brd->irq; brd->channels[i]->uart_port.uartclk = 14745600; brd->channels[i]->uart_port.type = PORT_JSM; brd->channels[i]->uart_port.iotype = UPIO_MEM; brd->channels[i]->uart_port.membase = brd->re_map_membase; brd->channels[i]->uart_port.fifosize = 16; brd->channels[i]->uart_port.ops = &jsm_ops; line = find_first_zero_bit(linemap, MAXLINES); if (line >= MAXLINES) { printk(KERN_INFO "jsm: linemap is full, added device failed\n"); continue; } else set_bit(line, linemap); brd->channels[i]->uart_port.line = line; rc = uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port); if (rc){ printk(KERN_INFO "jsm: Port %d failed. Aborting...\n", i); return rc; } else printk(KERN_INFO "jsm: Port %d added\n", i); } jsm_dbg(INIT, &brd->pci_dev, "finish\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong22175.68%116.67%
alexander y. fomichevalexander y. fomichev3712.67%116.67%
breno leitaobreno leitao196.51%233.33%
lennart sorensenlennart sorensen134.45%116.67%
joe perchesjoe perches20.68%116.67%
Total292100.00%6100.00%


int jsm_remove_uart_port(struct jsm_board *brd) { int i; struct jsm_channel *ch; if (!brd) return -ENXIO; jsm_dbg(INIT, &brd->pci_dev, "start\n"); /* * Initialize board structure elements. */ brd->nasync = brd->maxports; /* Set up channel variables */ for (i = 0; i < brd->nasync; i++) { if (!brd->channels[i]) continue; ch = brd->channels[i]; clear_bit(ch->uart_port.line, linemap); uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port); } jsm_dbg(INIT, &brd->pci_dev, "finish\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong11589.84%133.33%
alexander y. fomichevalexander y. fomichev118.59%133.33%
joe perchesjoe perches21.56%133.33%
Total128100.00%3100.00%


void jsm_input(struct jsm_channel *ch) { struct jsm_board *bd; struct tty_struct *tp; struct tty_port *port; u32 rmask; u16 head; u16 tail; int data_len; unsigned long lock_flags; int len = 0; int s = 0; int i = 0; jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n"); if (!ch) return; port = &ch->uart_port.state->port; tp = port->tty; bd = ch->ch_bd; if(!bd) return; spin_lock_irqsave(&ch->ch_lock, lock_flags); /* *Figure the number of characters in the buffer. *Exit immediately if none. */ rmask = RQUEUEMASK; head = ch->ch_r_head & rmask; tail = ch->ch_r_tail & rmask; data_len = (head - tail) & rmask; if (data_len == 0) { spin_unlock_irqrestore(&ch->ch_lock, lock_flags); return; } jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n"); /* *If the device is not open, or CREAD is off, flush *input data and return immediately. */ if (!tp || !C_CREAD(tp)) { jsm_dbg(READ, &ch->ch_bd->pci_dev, "input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum); ch->ch_r_head = tail; /* Force queue flow control to be released, if needed */ jsm_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, lock_flags); return; } /* * If we are throttled, simply don't read any data. */ if (ch->ch_flags & CH_STOPI) { spin_unlock_irqrestore(&ch->ch_lock, lock_flags); jsm_dbg(READ, &ch->ch_bd->pci_dev, "Port %d throttled, not reading any data. head: %x tail: %x\n", ch->ch_portnum, head, tail); return; } jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n"); len = tty_buffer_request_room(port, data_len); /* * len now contains the most amount of data we can copy, * bounded either by the flip buffer size or the amount * of data the card actually has pending... */ while (len) { s = ((head >= tail) ? head : RQUEUESIZE) - tail; s = min(s, len); if (s <= 0) break; /* * If conditions are such that ld needs to see all * UART errors, we will have to walk each character * and error byte and send them to the buffer one at * a time. */ if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { for (i = 0; i < s; i++) { /* * Give the Linux ld the flags in the * format it likes. */ if (*(ch->ch_equeue +tail +i) & UART_LSR_BI) tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_BREAK); else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE) tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_PARITY); else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE) tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_FRAME); else tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_NORMAL); } } else { tty_insert_flip_string(port, ch->ch_rqueue + tail, s); } tail += s; len -= s; /* Flip queue if needed */ tail &= rmask; } ch->ch_r_tail = tail & rmask; ch->ch_e_tail = tail & rmask; jsm_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, lock_flags); /* Tell the tty layer its okay to "eat" the data now */ tty_flip_buffer_push(port); jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n"); }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong44877.51%17.69%
v. ananda krishnanv. ananda krishnan9316.09%17.69%
jiri slabyjiri slaby193.29%430.77%
joe perchesjoe perches61.04%17.69%
jakob ostergaard jensenjakob ostergaard jensen40.69%17.69%
peter hurleypeter hurley30.52%17.69%
alan coxalan cox30.52%323.08%
al viroal viro20.35%17.69%
Total578100.00%13100.00%


static void jsm_carrier(struct jsm_channel *ch) { struct jsm_board *bd; int virt_carrier = 0; int phys_carrier = 0; jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n"); if (!ch) return; bd = ch->ch_bd; if (!bd) return; if (ch->ch_mistat & UART_MSR_DCD) { jsm_dbg(CARR, &ch->ch_bd->pci_dev, "mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD); phys_carrier = 1; } if (ch->ch_c_cflag & CLOCAL) virt_carrier = 1; jsm_dbg(CARR, &ch->ch_bd->pci_dev, "DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier); /* * Test for a VIRTUAL carrier transition to HIGH. */ if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) { /* * When carrier rises, wake any threads waiting * for carrier in the open routine. */ jsm_dbg(CARR, &ch->ch_bd->pci_dev, "carrier: virt DCD rose\n"); if (waitqueue_active(&(ch->ch_flags_wait))) wake_up_interruptible(&ch->ch_flags_wait); } /* * Test for a PHYSICAL carrier transition to HIGH. */ if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) { /* * When carrier rises, wake any threads waiting * for carrier in the open routine. */ jsm_dbg(CARR, &ch->ch_bd->pci_dev, "carrier: physical DCD rose\n"); if (waitqueue_active(&(ch->ch_flags_wait))) wake_up_interruptible(&ch->ch_flags_wait); } /* * Test for a PHYSICAL transition to low, so long as we aren't * currently ignoring physical transitions (which is what "virtual * carrier" indicates). * * The transition of the virtual carrier to low really doesn't * matter... it really only means "ignore carrier state", not * "make pretend that carrier is there". */ if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) && (phys_carrier == 0)) { /* * When carrier drops: * * Drop carrier on all open units. * * Flush queues, waking up any task waiting in the * line discipline. * * Send a hangup to the control terminal. * * Enable all select calls. */ if (waitqueue_active(&(ch->ch_flags_wait))) wake_up_interruptible(&ch->ch_flags_wait); } /* * Make sure that our cached values reflect the current reality. */ if (virt_carrier == 1) ch->ch_flags |= CH_FCAR; else ch->ch_flags &= ~CH_FCAR; if (phys_carrier == 1) ch->ch_flags |= CH_CD; else ch->ch_flags &= ~CH_CD; }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong32798.20%133.33%
joe perchesjoe perches51.50%133.33%
adrian bunkadrian bunk10.30%133.33%
Total333100.00%3100.00%


void jsm_check_queue_flow_control(struct jsm_channel *ch) { struct board_ops *bd_ops = ch->ch_bd->bd_ops; int qleft; /* Store how much space we have left in the queue */ if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0) qleft += RQUEUEMASK + 1; /* * Check to see if we should enforce flow control on our queue because * the ld (or user) isn't reading data out of our queue fast enuf. * * NOTE: This is done based on what the current flow control of the * port is set for. * * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt. * This will cause the UART's FIFO to back up, and force * the RTS signal to be dropped. * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to * the other side, in hopes it will stop sending data to us. * 3) NONE - Nothing we can do. We will simply drop any extra data * that gets sent into us when the queue fills up. */ if (qleft < 256) { /* HWFLOW */ if (ch->ch_c_cflag & CRTSCTS) { if(!(ch->ch_flags & CH_RECEIVER_OFF)) { bd_ops->disable_receiver(ch); ch->ch_flags |= (CH_RECEIVER_OFF); jsm_dbg(READ, &ch->ch_bd->pci_dev, "Internal queue hit hilevel mark (%d)! Turning off interrupts\n", qleft); } } /* SWFLOW */ else if (ch->ch_c_iflag & IXOFF) { if (ch->ch_stops_sent <= MAX_STOPS_SENT) { bd_ops->send_stop_character(ch); ch->ch_stops_sent++; jsm_dbg(READ, &ch->ch_bd->pci_dev, "Sending stop char! Times sent: %x\n", ch->ch_stops_sent); } } } /* * Check to see if we should unenforce flow control because * ld (or user) finally read enuf data out of our queue. * * NOTE: This is done based on what the current flow control of the * port is set for. * * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt. * This will cause the UART's FIFO to raise RTS back up, * which will allow the other side to start sending data again. * 2) SWFLOW (IXOFF) - Send a start character to * the other side, so it will start sending data to us again. * 3) NONE - Do nothing. Since we didn't do anything to turn off the * other side, we don't need to do anything now. */ if (qleft > (RQUEUESIZE / 2)) { /* HWFLOW */ if (ch->ch_c_cflag & CRTSCTS) { if (ch->ch_flags & CH_RECEIVER_OFF) { bd_ops->enable_receiver(ch); ch->ch_flags &= ~(CH_RECEIVER_OFF); jsm_dbg(READ, &ch->ch_bd->pci_dev, "Internal queue hit lowlevel mark (%d)! Turning on interrupts\n", qleft); } } /* SWFLOW */ else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) { ch->ch_stops_sent = 0; bd_ops->send_start_character(ch); jsm_dbg(READ, &ch->ch_bd->pci_dev, "Sending start char!\n"); } } }

Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong25793.80%133.33%
jesper juhljesper juhl114.01%133.33%
joe perchesjoe perches62.19%133.33%
Total274100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
wendy xiongwendy xiong297386.78%13.45%
v. ananda krishnanv. ananda krishnan932.71%13.45%
fabian frederickfabian frederick702.04%13.45%
alexander y. fomichevalexander y. fomichev561.63%13.45%
joe perchesjoe perches431.26%13.45%
thadeu lima de souza cascardothadeu lima de souza cascardo401.17%13.45%
jesper juhljesper juhl340.99%13.45%
alan coxalan cox210.61%620.69%
breno leitaobreno leitao200.58%310.34%
jiri slabyjiri slaby190.55%413.79%
konrad zapalowiczkonrad zapalowicz160.47%26.90%
lennart sorensenlennart sorensen130.38%13.45%
adrian bunkadrian bunk110.32%13.45%
al viroal viro40.12%13.45%
jakob ostergaard jensenjakob ostergaard jensen40.12%13.45%
burman yanburman yan30.09%13.45%
tejun heotejun heo30.09%13.45%
peter hurleypeter hurley30.09%13.45%
Total3426100.00%29100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}