* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
- * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
+ * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
*
* This is shared code between Digi's CVS archive and the
* Linux Kernel sources.
* Changing the source just for reformatting needlessly breaks
* our CVS diff history.
*
- * Send any bug fixes/changes to: Eng.Linux at digi dot com.
- * Thank you.
+ * Send any bug fixes/changes to: Eng.Linux at digi dot com.
+ * Thank you.
*/
/************************************************************************
- *
+ *
* This file implements the tty driver functionality for the
* Neo and ClassicBoard PCI based product lines.
- *
+ *
************************************************************************
*
* $Id: dgnc_tty.c,v 1.5 2013/04/30 19:18:30 markh Exp $
};
/************************************************************************
- *
+ *
* TTY Initialization/Cleanup Functions
- *
+ *
************************************************************************/
-
+
/*
* dgnc_tty_preinit()
*
memset(&brd->PrintDriver, 0, sizeof(struct tty_driver));
brd->SerialDriver.magic = TTY_DRIVER_MAGIC;
-
+
snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum);
brd->SerialDriver.name = brd->SerialName;
brd->SerialDriver.major = 0;
brd->SerialDriver.minor_start = 0;
brd->SerialDriver.num = brd->maxports;
- brd->SerialDriver.type = TTY_DRIVER_TYPE_SERIAL;
- brd->SerialDriver.subtype = SERIAL_TYPE_NORMAL;
+ brd->SerialDriver.type = TTY_DRIVER_TYPE_SERIAL;
+ brd->SerialDriver.subtype = SERIAL_TYPE_NORMAL;
brd->SerialDriver.init_termios = DgncDefaultTermios;
brd->SerialDriver.driver_name = DRVSTR;
brd->SerialDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
- /*
+ /*
* The kernel wants space to store pointers to
- * tty_struct's and termios's.
+ * tty_struct's and termios's.
*/
brd->SerialDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
if (!brd->SerialDriver.ttys)
brd->PrintDriver.major = brd->SerialDriver.major;
brd->PrintDriver.minor_start = 0x80;
brd->PrintDriver.num = brd->maxports;
- brd->PrintDriver.type = TTY_DRIVER_TYPE_SERIAL;
+ brd->PrintDriver.type = TTY_DRIVER_TYPE_SERIAL;
brd->PrintDriver.subtype = SERIAL_TYPE_NORMAL;
brd->PrintDriver.init_termios = DgncDefaultTermios;
brd->PrintDriver.driver_name = DRVSTR;
* dgnc_tty_uninit()
*
* Uninitialize the TTY portion of this driver. Free all memory and
- * resources.
+ * resources.
*/
void dgnc_tty_uninit(struct board_t *brd)
{
if (n == 0) {
return;
}
-
+
/*
* Copy as much data as will fit.
*/
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
-
+
head = ch->ch_w_head & WQUEUEMASK;
/*
remain = WQUEUESIZE - head;
if (n >= remain) {
- n -= remain;
+ n -= remain;
memcpy(ch->ch_wqueue + head, buf, remain);
head = 0;
buf += remain;
/*=======================================================================
*
* dgnc_input - Process received data.
- *
+ *
* ch - Pointer to channel structure.
- *
+ *
*=======================================================================*/
void dgnc_input(struct channel_t *ch)
{
DGNC_LOCK(ch->ch_lock, lock_flags);
- /*
- * Figure the number of characters in the buffer.
+ /*
+ * Figure the number of characters in the buffer.
* Exit immediately if none.
*/
rmask = RQUEUEMASK;
* If the device is not open, or CREAD is off,
* flush input data and return immediately.
*/
- if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) ||
+ if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) ||
!(tp->termios.c_cflag & CREAD) || (ch->ch_tun.un_flags & UN_CLOSING)) {
DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum));
if (!ld->ops->receive_buf) {
ch->ch_r_head = ch->ch_r_tail;
len = 0;
- }
+ }
}
if (len <= 0) {
*
* The flip buffers in the tty structure are no longer exposed,
* and probably will be going away eventually.
- *
+ *
* If we are completely raw, we don't need to go through a lot
* of the tty layers that exist.
* In this case, we take the shortest and fastest route we
break;
/*
- * If conditions are such that ld needs to see all
+ * 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.
}
-/************************************************************************
+/************************************************************************
* Determines when CARRIER changes state and takes appropriate
- * action.
+ * action.
************************************************************************/
void dgnc_carrier(struct channel_t *ch)
{
int virt_carrier = 0;
int phys_carrier = 0;
-
+
DPR_CARR(("dgnc_carrier called...\n"));
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) {
virt_carrier = 1;
- }
+ }
if (ch->ch_c_cflag & CLOCAL) {
virt_carrier = 1;
- }
+ }
DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier));
* "make pretend that carrier is there".
*/
if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) &&
- (phys_carrier == 0))
+ (phys_carrier == 0))
{
/*
tty_hangup(ch->ch_tun.un_tty);
}
- if (ch->ch_pun.un_open_count > 0) {
+ if (ch->ch_pun.un_open_count > 0) {
DPR_CARR(("Sending pr hangup\n"));
tty_hangup(ch->ch_pun.un_tty);
}
*/
if (virt_carrier == 1)
ch->ch_flags |= CH_FCAR;
- else
+ else
ch->ch_flags &= ~CH_FCAR;
if (phys_carrier == 1)
{
int testdiv;
int testrate_high;
- int testrate_low;
+ int testrate_low;
int deltahigh;
int deltalow;
* If we try to figure out what rate the board would use
* with the test divisor, it will be either equal or higher
* than the requested baud rate. If we then determine the
- * rate with a divisor one higher, we will get the next lower
+ * rate with a divisor one higher, we will get the next lower
* supported rate below the requested.
*/
testrate_high = ch->ch_bd->bd_dividend / testdiv;
break;
}
-
+
ch->ch_custom_speed = newrate;
return;
/************************************************************************
- *
+ *
* TTY Entry points and helper functions
- *
+ *
************************************************************************/
/*
dgnc_carrier(ch);
- /*
+ /*
* follow protocol for opening port
*/
}
-/*
+/*
* dgnc_block_til_ready()
*
* Wait for DCD, if needed.
*/
static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
-{
+{
int retval = 0;
struct un_t *un = NULL;
ulong lock_flags;
* If either unit is in the middle of the fragile part of close,
* we just cannot touch the channel safely.
* Go back to sleep, knowing that when the channel can be
- * touched safely, the close routine will signal the
+ * touched safely, the close routine will signal the
* ch_wait_flags to wake us back up.
*/
if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
* dgnc_tty_hangup()
*
* Hangup the port. Like a close, but don't wait for output to drain.
- */
+ */
static void dgnc_tty_hangup(struct tty_struct *tty)
{
struct un_t *un;
*/
APR(("tty->count is 1, un open count is %d\n", un->un_open_count));
un->un_open_count = 1;
- }
+ }
if (--un->un_open_count < 0) {
APR(("bad serial port open count of %d\n", un->un_open_count));
bd->bd_ops->assert_modem_signals(ch);
/*
- * Go to sleep to ensure RTS/DTR
+ * Go to sleep to ensure RTS/DTR
* have been dropped for modems to see it.
*/
if (ch->ch_close_delay) {
chars = thead - ttail + WQUEUESIZE;
}
- DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n",
+ DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n",
ch->ch_portnum, chars, thead, ttail));
return(chars);
}
-/*
+/*
* dgnc_maxcps_room
*
* Reduces bytes_available to the max number of characters
* that can be sent currently given the maxcps value, and
* returns the new bytes_available. This only affects printer
* output.
- */
+ */
static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available)
{
struct channel_t *ch = NULL;
}
else {
/* no room in the buffer */
- cps_limit = 0;
+ cps_limit = 0;
}
bytes_available = min(cps_limit, bytes_available);
* dgnc_tty_write_room()
*
* Return space available in Tx buffer
- */
+ */
static int dgnc_tty_write_room(struct tty_struct *tty)
{
struct channel_t *ch = NULL;
ret = dgnc_maxcps_room(tty, ret);
/*
- * If we are printer device, leave space for
+ * If we are printer device, leave space for
* possibly both the on and off strings.
*/
if (un->un_type == DGNC_PRINT) {
ret = 0;
DGNC_UNLOCK(ch->ch_lock, lock_flags);
-
+
DPR_WRITE(("dgnc_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
return(ret);
* dgnc_tty_put_char()
*
* Put a character into ch->ch_buf
- *
+ *
* - used by the line discipline for OPOST processing
*/
static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c)
/*
* If there is nothing left to copy, or I can't handle any more data, leave.
- */
+ */
if (count <= 0) {
DGNC_UNLOCK(ch->ch_lock, lock_flags);
return(0);
if (set & TIOCM_RTS) {
ch->ch_mostat |= UART_MCR_RTS;
- }
+ }
if (set & TIOCM_DTR) {
ch->ch_mostat |= UART_MCR_DTR;
- }
+ }
if (clear & TIOCM_RTS) {
ch->ch_mostat &= ~(UART_MCR_RTS);
return;
}
return;
-}
+}
/*
DPR_IOCTL(("dgnc_tty_send_xchar finish\n"));
printk("dgnc_tty_send_xchar finish\n");
return;
-}
+}
/*
- * dgnc_tty_digigeta()
+ * dgnc_tty_digigeta()
*
* Ioctl to get the information for ditty.
*
/*
- * dgnc_tty_digiseta()
+ * dgnc_tty_digiseta()
*
* Ioctl to set the information for ditty.
*
memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
- if (ch->ch_digi.digi_maxcps < 1)
+ if (ch->ch_digi.digi_maxcps < 1)
ch->ch_digi.digi_maxcps = 1;
- if (ch->ch_digi.digi_maxcps > 10000)
+ if (ch->ch_digi.digi_maxcps > 10000)
ch->ch_digi.digi_maxcps = 10000;
if (ch->ch_digi.digi_bufsize < 10)
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
return;
-
+
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
return;
-
+
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
return;
-
+
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
return;
-
+
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
}
-/*
+/*
* dgnc_tty_flush_chars()
*
* Flush the cook buffer
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
return;
-
+
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
/*
* dgnc_tty_flush_buffer()
- *
+ *
* Flush Tx buffer (make in == out)
*/
static void dgnc_tty_flush_buffer(struct tty_struct *tty)
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
return;
-
+
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
return;
* The IOCTL function and all of its helpers
*
*****************************************************************************/
-
+
/*
* dgnc_tty_ioctl()
*
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
return (-ENODEV);
- DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
DGNC_LOCK(ch->ch_lock, lock_flags);
case TCSBRK:
/*
- * TCSBRK is SVID version: non-zero arg --> no break
+ * TCSBRK is SVID version: non-zero arg --> no break
* this behaviour is exploited by tcdrain().
*
* According to POSIX.1 spec (7.2.2.1.2) breaks should be
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
return(0);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
return(0);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
return(0);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
return(0);
-
+
case TIOCMGET:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
return(dgnc_get_modem_info(ch, uarg));
/*
* Here are any additional ioctl's that we want to implement
*/
-
- case TCFLSH:
+
+ case TCFLSH:
/*
* The linux tty driver doesn't have a flush
* input routine for the driver, assuming all backed
* act on the ioctl, but then lie and say we didn't
* so the line discipline will process the flush
* also.
- */
+ */
rc = tty_check_change(tty);
if (rc) {
DGNC_UNLOCK(ch->ch_lock, lock_flags);
}
}
- /* pretend we didn't recognize this IOCTL */
+ /* pretend we didn't recognize this IOCTL */
DGNC_UNLOCK(ch->ch_lock, lock_flags);
return(-ENOIOCTLCMD);
case TCSETSF:
return(-EINTR);
}
- DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
/* pretend we didn't recognize this */
}
/* pretend we didn't recognize this */
- return(-ENOIOCTLCMD);
+ return(-ENOIOCTLCMD);
case TCXONC:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
case DIGI_SETA:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
return(dgnc_tty_digiseta(tty, uarg));
-
+
case DIGI_LOOPBACK:
{
uint loopback = 0;
return(rc);
DGNC_LOCK(ch->ch_lock, lock_flags);
- /* Enable/disable internal loopback for this port */
+ /* Enable/disable internal loopback for this port */
if (loopback)
ch->ch_flags |= CH_LOOPBACK;
else
DGNC_UNLOCK(ch->ch_lock, lock_flags);
DPR_IOCTL(("dgnc_tty_ioctl - in default\n"));
- DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
dgnc_ioctl_name(cmd), cmd, arg));
return(-ENOIOCTLCMD);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
+ DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
dgnc_ioctl_name(cmd), cmd, arg));
-
+
return(0);
}