^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Serial driver for the amiga builtin port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This code was created by taking serial.c version 4.30 from kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * release 2.3.22, replacing all hardware related stuff with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * corresponding amiga hardware actions, and removing all irrelevant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * code. As a consequence, it uses many of the constants and names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * associated with the registers and bits of 16550 compatible UARTS -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * but only to keep track of status, etc in the state variables. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * was done this was to make it easier to keep the code in line with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * (non hardware specific) changes to serial.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * The port is registered with the tty driver as minor device 64, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * therefore other ports should should only use 65 upwards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Richard Lucock 28/12/99
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Copyright (C) 1991, 1992 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * 1998, 1999 Theodore Ts'o
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Set of debugging defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #undef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #undef SERIAL_DEBUG_OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #undef SERIAL_DEBUG_FLOW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Sanity checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) tty->name, (info->tport.flags), serial_driver->refcount,info->count,tty->count,s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define DBG_CNT(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * End of serial driver configuration section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/serial_reg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static char *serial_version = "4.30";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include <linux/circ_buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <asm/amigahw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #include <asm/amigaints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct serial_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct tty_port tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct circ_buf xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct async_icount icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int baud_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int xmit_fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int read_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ignore_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int quot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int IER; /* Interrupt Enable Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int MCR; /* Modem control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int x_char; /* xon/xoff character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define custom amiga_custom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static char *serial_name = "Amiga-builtin serial driver";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static struct tty_driver *serial_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* number of characters left in xmit buffer before we ask for more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define WAKEUP_CHARS 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static unsigned char current_ctl_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void change_speed(struct tty_struct *tty, struct serial_state *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct ktermios *old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct serial_state rs_table[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define NR_PORTS ARRAY_SIZE(rs_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define serial_isroot() (capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* some serial hardware definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define SDR_OVRUN (1<<15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define SDR_RBF (1<<14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define SDR_TBE (1<<13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define SDR_TSRE (1<<12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define SERPER_PARENB (1<<15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define AC_SETCLR (1<<15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define AC_UARTBRK (1<<11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define SER_DTR (1<<7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define SER_RTS (1<<6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define SER_DCD (1<<5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define SER_CTS (1<<4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define SER_DSR (1<<3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static __inline__ void rtsdtr_ctrl(int bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ciab.pra = ((bits & (SER_RTS | SER_DTR)) ^ (SER_RTS | SER_DTR)) | (ciab.pra & ~(SER_RTS | SER_DTR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * rs_stop() and rs_start()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * This routines are called before setting or resetting tty->stopped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * They enable or disable transmitter interrupts, as necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static void rs_stop(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (info->IER & UART_IER_THRI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) info->IER &= ~UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* disable Tx interrupt and remove any pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) custom.intena = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) custom.intreq = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void rs_start(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (info->xmit.head != info->xmit.tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) && info->xmit.buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) && !(info->IER & UART_IER_THRI)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) info->IER |= UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) custom.intena = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* set a pending Tx Interrupt, transmitter should restart now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) custom.intreq = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * ----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Here starts the interrupt handling routines. All of the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * subroutines are declared as inline and are folded into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * rs_interrupt(). They were separated out for readability's sake.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Note: rs_interrupt() is a "fast" interrupt, which means that it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * runs with interrupts turned off. People who may want to modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * rs_interrupt() should try to keep the interrupt handler as fast as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * possible. After you are done making modifications, it is not a bad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * idea to do:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * and look at the resulting assemble code in serial.s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * -----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static void receive_chars(struct serial_state *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int serdatr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned char ch, flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct async_icount *icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int oe = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) icount = &info->icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) status = UART_LSR_DR; /* We obviously have a character! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) serdatr = custom.serdatr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) custom.intreq = IF_RBF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if((serdatr & 0x1ff) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) status |= UART_LSR_BI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if(serdatr & SDR_OVRUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) status |= UART_LSR_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ch = serdatr & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) icount->rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) printk("DR%02x:%02x...", ch, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) flag = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * We don't handle parity or frame errors - but I have left
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * the code in, since I'm not sure that the errors can't be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * detected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (status & (UART_LSR_BI | UART_LSR_PE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) UART_LSR_FE | UART_LSR_OE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * For statistics only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (status & UART_LSR_BI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) status &= ~(UART_LSR_FE | UART_LSR_PE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) icount->brk++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } else if (status & UART_LSR_PE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) icount->parity++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) else if (status & UART_LSR_FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) icount->frame++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (status & UART_LSR_OE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) icount->overrun++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * Now check to see if character should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * ignored, and mask off conditions which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * should be ignored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (status & info->ignore_status_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) status &= info->read_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (status & (UART_LSR_BI)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) printk("handling break....");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) flag = TTY_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (info->tport.flags & ASYNC_SAK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) do_SAK(info->tport.tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) } else if (status & UART_LSR_PE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) flag = TTY_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) else if (status & UART_LSR_FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) flag = TTY_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (status & UART_LSR_OE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Overrun is special, since it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * reported immediately, and doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * affect the current character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) oe = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) tty_insert_flip_char(&info->tport, ch, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (oe == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) tty_insert_flip_char(&info->tport, 0, TTY_OVERRUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) tty_flip_buffer_push(&info->tport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static void transmit_chars(struct serial_state *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) custom.intreq = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (info->x_char) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) custom.serdat = info->x_char | 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) info->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) info->x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (info->xmit.head == info->xmit.tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) || info->tport.tty->stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) || info->tport.tty->hw_stopped) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) info->IER &= ~UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) custom.intena = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) info->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (CIRC_CNT(info->xmit.head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) info->xmit.tail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) tty_wakeup(info->tport.tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) printk("THRE...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (info->xmit.head == info->xmit.tail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) custom.intena = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) info->IER &= ~UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static void check_modem_status(struct serial_state *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct tty_port *port = &info->tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned char dstatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct async_icount *icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* Determine bits that have changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dstatus = status ^ current_ctl_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) current_ctl_bits = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (dstatus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) icount = &info->icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* update input line counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (dstatus & SER_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) icount->dsr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (dstatus & SER_DCD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) icount->dcd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (dstatus & SER_CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) icount->cts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) wake_up_interruptible(&port->delta_msr_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (tty_port_check_carrier(port) && (dstatus & SER_DCD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) printk("ttyS%d CD now %s...", info->line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) (!(status & SER_DCD)) ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!(status & SER_DCD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) wake_up_interruptible(&port->open_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) #ifdef SERIAL_DEBUG_OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) printk("doing serial hangup...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (port->tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) tty_hangup(port->tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (tty_port_cts_enabled(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (port->tty->hw_stopped) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!(status & SER_CTS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) printk("CTS tx start...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) port->tty->hw_stopped = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) info->IER |= UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) custom.intena = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* set a pending Tx Interrupt, transmitter should restart now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) custom.intreq = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) tty_wakeup(port->tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if ((status & SER_CTS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) printk("CTS tx stop...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) port->tty->hw_stopped = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) info->IER &= ~UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* disable Tx interrupt and remove any pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) custom.intena = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) custom.intreq = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static irqreturn_t ser_vbl_int( int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* vbl is just a periodic interrupt we tie into to update modem status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct serial_state *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * TBD - is it better to unregister from this interrupt or to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * ignore it if MSI is clear ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if(info->IER & UART_IER_MSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) check_modem_status(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static irqreturn_t ser_rx_int(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct serial_state *info = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) printk("ser_rx_int...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!info->tport.tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) receive_chars(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) printk("end.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static irqreturn_t ser_tx_int(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct serial_state *info = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (custom.serdatr & SDR_TBE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) printk("ser_tx_int...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!info->tport.tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) transmit_chars(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) #ifdef SERIAL_DEBUG_INTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) printk("end.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * Here ends the serial interrupt routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * ---------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * Low level utility subroutines for the serial driver: routines to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * figure out the appropriate timeout for an interrupt chain, routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * to initialize and startup a serial port, and routines to shutdown a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * serial port. Useful stuff like that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * ---------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int startup(struct tty_struct *tty, struct serial_state *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct tty_port *port = &info->tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int retval=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) unsigned long page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) page = get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (tty_port_initialized(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (info->xmit.buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) info->xmit.buf = (unsigned char *) page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) #ifdef SERIAL_DEBUG_OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) printk("starting up ttys%d ...", info->line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* Clear anything in the input buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) custom.intreq = IF_RBF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (serial_isroot()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) set_bit(TTY_IO_ERROR, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* enable both Rx and Tx interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) info->IER = UART_IER_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* remember current state of the DCD and CTS bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) current_ctl_bits = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) info->MCR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (C_BAUD(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) info->MCR = SER_DTR | SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) clear_bit(TTY_IO_ERROR, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) info->xmit.head = info->xmit.tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * and set the speed of the serial port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) change_speed(tty, info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) tty_port_set_initialized(port, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) errout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * This routine will shutdown a serial port; interrupts are disabled, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * DTR is dropped if the hangup on close termio flag is on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static void shutdown(struct tty_struct *tty, struct serial_state *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct serial_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (!tty_port_initialized(&info->tport))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) state = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) #ifdef SERIAL_DEBUG_OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) printk("Shutting down serial port %d ....\n", info->line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) local_irq_save(flags); /* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * here so the queue might never be waken up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) wake_up_interruptible(&info->tport.delta_msr_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * Free the IRQ, if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) free_irq(IRQ_AMIGA_VERTB, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (info->xmit.buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) free_page((unsigned long) info->xmit.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) info->xmit.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) info->IER = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) custom.intena = IF_RBF | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* disable break condition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) custom.adkcon = AC_UARTBRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (C_HUPCL(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) info->MCR &= ~(SER_DTR|SER_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) set_bit(TTY_IO_ERROR, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) tty_port_set_initialized(&info->tport, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * This routine is called to set the UART divisor registers to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * the specified baud rate for a serial port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static void change_speed(struct tty_struct *tty, struct serial_state *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct tty_port *port = &info->tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int quot = 0, baud_base, baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) unsigned cflag, cval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) cflag = tty->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* Byte size is always 8 bits plus parity bit if requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) cval = 3; bits = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (cflag & CSTOPB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) cval |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) bits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (cflag & PARENB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) cval |= UART_LCR_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) bits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!(cflag & PARODD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) cval |= UART_LCR_EPAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) #ifdef CMSPAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (cflag & CMSPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) cval |= UART_LCR_SPAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* Determine divisor based on baud rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) baud = tty_get_baud_rate(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (!baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) baud = 9600; /* B0 transition handled in rs_set_termios */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) baud_base = info->baud_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (baud == 38400 && (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) quot = info->custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (baud == 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /* Special case since 134 is really 134.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) quot = (2*baud_base / 269);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) else if (baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) quot = baud_base / baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* If the quotient is zero refuse the change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!quot && old_termios) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* FIXME: Will need updating for new tty in the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) tty->termios.c_cflag &= ~CBAUD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) tty->termios.c_cflag |= (old_termios->c_cflag & CBAUD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) baud = tty_get_baud_rate(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (!baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) baud = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (baud == 38400 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) quot = info->custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (baud == 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* Special case since 134 is really 134.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) quot = (2*baud_base / 269);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) else if (baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) quot = baud_base / baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* As a last resort, if the quotient is zero, default to 9600 bps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (!quot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) quot = baud_base / 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) info->quot = quot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) info->timeout += HZ/50; /* Add .02 seconds of slop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* CTS flow control flag and modem status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) info->IER &= ~UART_IER_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (port->flags & ASYNC_HARDPPS_CD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) info->IER |= UART_IER_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) tty_port_set_cts_flow(port, cflag & CRTSCTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (cflag & CRTSCTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) info->IER |= UART_IER_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) tty_port_set_check_carrier(port, ~cflag & CLOCAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (~cflag & CLOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) info->IER |= UART_IER_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* TBD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * Does clearing IER_MSI imply that we should disable the VBL interrupt ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * Set up parity check flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (I_INPCK(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (I_BRKINT(tty) || I_PARMRK(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) info->read_status_mask |= UART_LSR_BI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * Characters to ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) info->ignore_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (I_IGNPAR(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (I_IGNBRK(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) info->ignore_status_mask |= UART_LSR_BI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * If we're ignore parity and break indicators, ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * overruns too. (For real raw support).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (I_IGNPAR(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) info->ignore_status_mask |= UART_LSR_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * !!! ignore all characters if CREAD is not set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if ((cflag & CREAD) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) info->ignore_status_mask |= UART_LSR_DR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) short serper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* Set up the baud rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) serper = quot - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* Enable or disable parity bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if(cval & UART_LCR_PARITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) serper |= (SERPER_PARENB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) custom.serper = serper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static int rs_put_char(struct tty_struct *tty, unsigned char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct serial_state *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (!info->xmit.buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (CIRC_SPACE(info->xmit.head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) info->xmit.tail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) SERIAL_XMIT_SIZE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) info->xmit.buf[info->xmit.head++] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) info->xmit.head &= SERIAL_XMIT_SIZE-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static void rs_flush_chars(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (info->xmit.head == info->xmit.tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) || tty->stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) || tty->hw_stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) || !info->xmit.buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) info->IER |= UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) custom.intena = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* set a pending Tx Interrupt, transmitter should restart now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) custom.intreq = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int c, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!info->xmit.buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) c = CIRC_SPACE_TO_END(info->xmit.head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) info->xmit.tail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) SERIAL_XMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (count < c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) c = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (c <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) memcpy(info->xmit.buf + info->xmit.head, buf, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) info->xmit.head = ((info->xmit.head + c) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) (SERIAL_XMIT_SIZE-1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) buf += c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) count -= c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ret += c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (info->xmit.head != info->xmit.tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) && !tty->stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) && !tty->hw_stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) && !(info->IER & UART_IER_THRI)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) info->IER |= UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) custom.intena = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* set a pending Tx Interrupt, transmitter should restart now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) custom.intreq = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static int rs_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static int rs_chars_in_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static void rs_flush_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) info->xmit.head = info->xmit.tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) tty_wakeup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * This function is used to send a high-priority XON/XOFF character to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static void rs_send_xchar(struct tty_struct *tty, char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) info->x_char = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* Make sure transmit interrupts are on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* Check this ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if(!(custom.intenar & IF_TBE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) custom.intena = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* set a pending Tx Interrupt, transmitter should restart now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) custom.intreq = IF_SETCLR | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) info->IER |= UART_IER_THRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * rs_throttle()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * This routine is called by the upper-layer tty layer to signal that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * incoming characters should be throttled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static void rs_throttle(struct tty_struct * tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) #ifdef SERIAL_DEBUG_THROTTLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) printk("throttle %s ....\n", tty_name(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (I_IXOFF(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) rs_send_xchar(tty, STOP_CHAR(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (C_CRTSCTS(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) info->MCR &= ~SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static void rs_unthrottle(struct tty_struct * tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) #ifdef SERIAL_DEBUG_THROTTLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) printk("unthrottle %s ....\n", tty_name(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (I_IXOFF(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (info->x_char)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) info->x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) rs_send_xchar(tty, START_CHAR(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (C_CRTSCTS(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) info->MCR |= SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * rs_ioctl() and friends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct serial_state *state = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) tty_lock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) ss->line = tty->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ss->port = state->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ss->flags = state->tport.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) ss->xmit_fifo_size = state->xmit_fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ss->baud_base = state->baud_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) ss->close_delay = state->tport.close_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ss->closing_wait = state->tport.closing_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ss->custom_divisor = state->custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) tty_unlock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct serial_state *state = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct tty_port *port = &state->tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) bool change_spd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) tty_lock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ss->custom_divisor != state->custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (ss->irq || ss->port != state->port ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) ss->xmit_fifo_size != state->xmit_fifo_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) tty_unlock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (!serial_isroot()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if ((ss->baud_base != state->baud_base) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) (ss->close_delay != port->close_delay) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) (ss->closing_wait != port->closing_wait) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) (ss->xmit_fifo_size != state->xmit_fifo_size) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ((ss->flags & ~ASYNC_USR_MASK) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) (port->flags & ~ASYNC_USR_MASK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) tty_unlock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) port->flags = ((port->flags & ~ASYNC_USR_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) (ss->flags & ASYNC_USR_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) state->custom_divisor = ss->custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) goto check_and_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (ss->baud_base < 9600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) tty_unlock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * OK, past this point, all the error checking has been done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * At this point, we start making changes.....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) state->baud_base = ss->baud_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) port->flags = ((port->flags & ~ASYNC_FLAGS) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) (ss->flags & ASYNC_FLAGS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) state->custom_divisor = ss->custom_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) port->close_delay = ss->close_delay * HZ/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) port->closing_wait = ss->closing_wait * HZ/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) check_and_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (tty_port_initialized(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (change_spd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* warn about deprecation unless clearing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (ss->flags & ASYNC_SPD_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) change_speed(tty, state, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) retval = startup(tty, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) tty_unlock(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * get_lsr_info - get line status register info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * Purpose: Let user call ioctl() to get info when the UART physically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * is emptied. On bus types like RS485, the transmitter must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * release the bus after transmitting. This must be done when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * the transmit shift register is empty, not be done when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * transmit holding register is empty. This functionality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * allows an RS485 driver to be written in user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) static int get_lsr_info(struct serial_state *info, unsigned int __user *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) unsigned int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) status = custom.serdatr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (copy_to_user(value, &result, sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) static int rs_tiocmget(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) unsigned char control, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (tty_io_error(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) control = info->MCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) status = ciab.pra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return ((control & SER_RTS) ? TIOCM_RTS : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) | ((control & SER_DTR) ? TIOCM_DTR : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) | (!(status & SER_DCD) ? TIOCM_CAR : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) | (!(status & SER_DSR) ? TIOCM_DSR : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) | (!(status & SER_CTS) ? TIOCM_CTS : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int rs_tiocmset(struct tty_struct *tty, unsigned int set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (tty_io_error(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (set & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) info->MCR |= SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (set & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) info->MCR |= SER_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (clear & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) info->MCR &= ~SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (clear & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) info->MCR &= ~SER_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * rs_break() --- routine which turns the break handling on or off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static int rs_break(struct tty_struct *tty, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (break_state == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) custom.adkcon = AC_SETCLR | AC_UARTBRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) custom.adkcon = AC_UARTBRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * Return: write counters to the user passed counter struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * NB: both 1->0 and 0->1 transitions are counted except for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * RI where only 0->1 is counted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) static int rs_get_icount(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) struct serial_icounter_struct *icount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) struct async_icount cnow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) cnow = info->icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) icount->cts = cnow.cts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) icount->dsr = cnow.dsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) icount->rng = cnow.rng;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) icount->dcd = cnow.dcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) icount->rx = cnow.rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) icount->tx = cnow.tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) icount->frame = cnow.frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) icount->overrun = cnow.overrun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) icount->parity = cnow.parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) icount->brk = cnow.brk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) icount->buf_overrun = cnow.buf_overrun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) static int rs_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct async_icount cprev, cnow; /* kernel counter temps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if ((cmd != TIOCSERCONFIG) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (tty_io_error(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) case TIOCSERCONFIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case TIOCSERGETLSR: /* Get line status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return get_lsr_info(info, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * - mask passed in arg for lines of interest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * Caller should use TIOCGICOUNT to see which one it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) case TIOCMIWAIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) /* note the counters on entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) cprev = info->icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) prepare_to_wait(&info->tport.delta_msr_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) &wait, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) cnow = info->icount; /* atomic copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ret = -EIO; /* no change => error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) /* see if a signal did it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) ret = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) cprev = cnow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) finish_wait(&info->tport.delta_msr_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) unsigned int cflag = tty->termios.c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) change_speed(tty, info, old_termios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /* Handle transition to B0 status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) info->MCR &= ~(SER_DTR|SER_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) /* Handle transition away from B0 status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) info->MCR |= SER_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (!C_CRTSCTS(tty) || !tty_throttled(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) info->MCR |= SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* Handle turning off CRTSCTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) tty->hw_stopped = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) rs_start(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * No need to wake up processes in open wait, since they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * sample the CLOCAL flag once, and don't recheck it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * XXX It's not clear whether the current behavior is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * or not. Hence, this may change.....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) wake_up_interruptible(&info->open_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * rs_close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * This routine is called when the serial port gets closed. First, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * wait for the last remaining data to be sent. Then, we unlink its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * async structure from the interrupt chain if necessary, and we free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * that IRQ if nothing is left in the chain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) static void rs_close(struct tty_struct *tty, struct file * filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) struct serial_state *state = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) struct tty_port *port = &state->tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (tty_port_close_start(port, tty, filp) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * At this point we stop accepting input. To do this, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) * disable the receive line status interrupts, and tell the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) * interrupt driver to stop checking the data ready bit in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) * line status register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) state->read_status_mask &= ~UART_LSR_DR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (tty_port_initialized(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /* disable receive interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) custom.intena = IF_RBF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) /* clear any pending receive interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) custom.intreq = IF_RBF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * Before we drop DTR, make sure the UART transmitter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * has completely drained; this is especially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * important if there is a transmit FIFO!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) rs_wait_until_sent(tty, state->timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) shutdown(tty, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) rs_flush_buffer(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) tty_ldisc_flush(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) port->tty = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) tty_port_close_end(port, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * rs_wait_until_sent() --- wait until the transmitter is empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) unsigned long orig_jiffies, char_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) int lsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (info->xmit_fifo_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return; /* Just in case.... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) orig_jiffies = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * Set the check interval to be 1/5 of the estimated time to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * send a single character, and make it at least 1. The check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) * interval should also be less than the timeout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * Note: we have to use pretty tight timings here to satisfy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * the NIST-PCTS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) char_time = char_time / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (char_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) char_time = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) char_time = min_t(unsigned long, char_time, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * If the transmitter hasn't cleared in twice the approximate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * amount of time to send the entire FIFO, it probably won't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * ever clear. This assumes the UART isn't doing flow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * control, which is currently the case. Hence, if it ever
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * takes longer than info->timeout, this is probably due to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * UART bug of some kind. So, we clamp the timeout parameter at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * 2*info->timeout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (!timeout || timeout > 2*info->timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) timeout = 2*info->timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) printk("jiff=%lu...", jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) while(!((lsr = custom.serdatr) & SDR_TSRE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) msleep_interruptible(jiffies_to_msecs(char_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (timeout && time_after(jiffies, orig_jiffies + timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) static void rs_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) struct serial_state *info = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) rs_flush_buffer(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) shutdown(tty, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) info->tport.count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) tty_port_set_active(&info->tport, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) info->tport.tty = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) wake_up_interruptible(&info->tport.open_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) * This routine is called whenever a serial port is opened. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * enables interrupts for a serial port, linking in its async structure into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) * the IRQ chain. It also performs the serial-specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * initialization for the tty structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) static int rs_open(struct tty_struct *tty, struct file * filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) struct serial_state *info = rs_table + tty->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) struct tty_port *port = &info->tport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) port->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) port->tty = tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) tty->driver_data = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) tty->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) retval = startup(tty, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) return tty_port_block_til_ready(port, tty, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * /proc fs routines....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) static inline void line_info(struct seq_file *m, int line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) struct serial_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) char stat_buf[30], control, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) seq_printf(m, "%d: uart:amiga_builtin", line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) status = ciab.pra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) control = tty_port_initialized(&state->tport) ? state->MCR : status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) stat_buf[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) stat_buf[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) if(!(control & SER_RTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) strcat(stat_buf, "|RTS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if(!(status & SER_CTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) strcat(stat_buf, "|CTS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if(!(control & SER_DTR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) strcat(stat_buf, "|DTR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if(!(status & SER_DSR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) strcat(stat_buf, "|DSR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if(!(status & SER_DCD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) strcat(stat_buf, "|CD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (state->quot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) seq_printf(m, " baud:%d", state->baud_base / state->quot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (state->icount.frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) seq_printf(m, " fe:%d", state->icount.frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (state->icount.parity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) seq_printf(m, " pe:%d", state->icount.parity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (state->icount.brk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) seq_printf(m, " brk:%d", state->icount.brk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (state->icount.overrun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) seq_printf(m, " oe:%d", state->icount.overrun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * Last thing is the RS-232 status lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) seq_printf(m, " %s\n", stat_buf+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) static int rs_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) line_info(m, 0, &rs_table[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) * ---------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) * rs_init() and friends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) * rs_init() is called at boot-time to initialize the serial driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) * ---------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * This routine prints out the appropriate serial driver version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * number, and identifies which options were configured into this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) static void show_serial_version(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) static const struct tty_operations serial_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) .open = rs_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) .close = rs_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) .write = rs_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) .put_char = rs_put_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) .flush_chars = rs_flush_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) .write_room = rs_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) .chars_in_buffer = rs_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) .flush_buffer = rs_flush_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) .ioctl = rs_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) .throttle = rs_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) .unthrottle = rs_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) .set_termios = rs_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) .stop = rs_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) .start = rs_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) .hangup = rs_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) .break_ctl = rs_break,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) .send_xchar = rs_send_xchar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) .wait_until_sent = rs_wait_until_sent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) .tiocmget = rs_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) .tiocmset = rs_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) .get_icount = rs_get_icount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .set_serial = set_serial_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .get_serial = get_serial_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) .proc_show = rs_proc_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) static int amiga_carrier_raised(struct tty_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) return !(ciab.pra & SER_DCD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) static void amiga_dtr_rts(struct tty_port *port, int raise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) struct serial_state *info = container_of(port, struct serial_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) tport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (raise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) info->MCR |= SER_DTR|SER_RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) info->MCR &= ~(SER_DTR|SER_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) rtsdtr_ctrl(info->MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) static const struct tty_port_operations amiga_port_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) .carrier_raised = amiga_carrier_raised,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) .dtr_rts = amiga_dtr_rts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) * The serial driver boot-time initialization code!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) static int __init amiga_serial_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) struct serial_state * state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) serial_driver = alloc_tty_driver(NR_PORTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (!serial_driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) show_serial_version();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) /* Initialize the tty_driver structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) serial_driver->driver_name = "amiserial";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) serial_driver->name = "ttyS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) serial_driver->major = TTY_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) serial_driver->minor_start = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) serial_driver->subtype = SERIAL_TYPE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) serial_driver->init_termios = tty_std_termios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) serial_driver->init_termios.c_cflag =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) B9600 | CS8 | CREAD | HUPCL | CLOCAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) serial_driver->flags = TTY_DRIVER_REAL_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) tty_set_operations(serial_driver, &serial_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) state = rs_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) state->port = (int)&custom.serdatr; /* Just to give it a value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) state->custom_divisor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) state->icount.cts = state->icount.dsr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) state->icount.rng = state->icount.dcd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) state->icount.rx = state->icount.tx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) state->icount.frame = state->icount.parity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) state->icount.overrun = state->icount.brk = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) tty_port_init(&state->tport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) state->tport.ops = &amiga_port_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) tty_port_link_device(&state->tport, serial_driver, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) error = tty_register_driver(serial_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) goto fail_put_tty_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /* Hardware set up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) state->baud_base = amiga_colorclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) state->xmit_fifo_size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) /* set ISRs, and then disable the rx interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) goto fail_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) "serial RX", state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) goto fail_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /* turn off Rx and Tx interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) custom.intena = IF_RBF | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) /* clear any pending interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) custom.intreq = IF_RBF | IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) * set the appropriate directions for the modem control flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) * and clear RTS and DTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) platform_set_drvdata(pdev, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) fail_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) free_irq(IRQ_AMIGA_TBE, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) fail_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) tty_unregister_driver(serial_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) fail_put_tty_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) tty_port_destroy(&state->tport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) put_tty_driver(serial_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) static int __exit amiga_serial_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) struct serial_state *state = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) /* printk("Unloading %s: version %s\n", serial_name, serial_version); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) error = tty_unregister_driver(serial_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) printk("SERIAL: failed to unregister serial driver (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) put_tty_driver(serial_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) tty_port_destroy(&state->tport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) free_irq(IRQ_AMIGA_TBE, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) free_irq(IRQ_AMIGA_RBF, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) static struct platform_driver amiga_serial_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) .remove = __exit_p(amiga_serial_remove),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) .name = "amiga-serial",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * Serial console driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) static void amiga_serial_putc(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) custom.serdat = (unsigned char)c | 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) while (!(custom.serdatr & 0x2000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * Print a string to the serial port trying not to disturb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) * any possible real use of the port...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * The console must be locked when we get here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) static void serial_console_write(struct console *co, const char *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) unsigned count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) unsigned short intena = custom.intenar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) custom.intena = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) while (count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (*s == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) amiga_serial_putc('\r');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) amiga_serial_putc(*s++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) custom.intena = IF_SETCLR | (intena & IF_TBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) static struct tty_driver *serial_console_device(struct console *c, int *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) *index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) return serial_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) static struct console sercons = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) .name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) .write = serial_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) .device = serial_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) * Register console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) static int __init amiserial_console_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) if (!MACH_IS_AMIGA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) register_console(&sercons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) console_initcall(amiserial_console_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) MODULE_ALIAS("platform:amiga-serial");