summaryrefslogtreecommitdiff
path: root/drivers/char/serial167.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-02-22 16:57:21 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-22 16:57:21 -0800
commit4a6514e6d096716fb7bedf238efaaca877e2a7e8 (patch)
treee3601ee168cca90307ac91e750a86d6ed04eab01 /drivers/char/serial167.c
parent282361a046edd9d58a134f358a3f65a7cb8655d9 (diff)
downloadlinux-4a6514e6d096716fb7bedf238efaaca877e2a7e8.tar.gz
linux-4a6514e6d096716fb7bedf238efaaca877e2a7e8.tar.bz2
linux-4a6514e6d096716fb7bedf238efaaca877e2a7e8.zip
tty: move obsolete and broken tty drivers to drivers/staging/tty/
As planned by Arnd Bergmann, this moves the following drivers to the drivers/staging/tty/ directory where they will be removed after 2.6.41 if no one steps up to claim them. epca epca ip2 istallion riscom8 serial167 specialix stallion Cc: Arnd Bergmann <arnd@arndb.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Jiri Slaby <jslaby@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/serial167.c')
-rw-r--r--drivers/char/serial167.c2489
1 files changed, 0 insertions, 2489 deletions
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
deleted file mode 100644
index 674af6933978..000000000000
--- a/drivers/char/serial167.c
+++ /dev/null
@@ -1,2489 +0,0 @@
-/*
- * linux/drivers/char/serial167.c
- *
- * Driver for MVME166/7 board serial ports, which are via a CD2401.
- * Based very much on cyclades.c.
- *
- * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * ==============================================================
- *
- * static char rcsid[] =
- * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
- *
- * linux/kernel/cyclades.c
- *
- * Maintained by Marcio Saito (cyclades@netcom.com) and
- * Randolph Bentson (bentson@grieg.seaslug.org)
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992 Linus Torvalds. It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- *
- * This version does not support shared irq's.
- *
- * $Log: cyclades.c,v $
- * Revision 1.36.1.4 1995/03/29 06:14:14 bentson
- * disambiguate between Cyclom-16Y and Cyclom-32Ye;
- *
- * Changes:
- *
- * 200 lines of changes record removed - RGH 11-10-95, starting work on
- * converting this to drive serial ports on mvme166 (cd2401).
- *
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
- * - get rid of verify_area
- * - use get_user to access memory from userspace in set_threshold,
- * set_default_threshold and set_timeout
- * - don't use the panic function in serial167_init
- * - do resource release on failure on serial167_init
- * - include missing restore_flags in mvme167_serial_console_setup
- *
- * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
- * - replace bottom half handler with task queue handler
- */
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/serial167.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/tty_flip.h>
-#include <linux/gfp.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mvme16xhw.h>
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include <asm/uaccess.h>
-#include <linux/init.h>
-
-#define SERIAL_PARANOIA_CHECK
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_THROTTLE
-#undef SERIAL_DEBUG_OTHER
-#undef SERIAL_DEBUG_IO
-#undef SERIAL_DEBUG_COUNT
-#undef SERIAL_DEBUG_DTR
-#undef CYCLOM_16Y_HACK
-#define CYCLOM_ENABLE_MONITORING
-
-#define WAKEUP_CHARS 256
-
-#define STD_COM_FLAGS (0)
-
-static struct tty_driver *cy_serial_driver;
-extern int serial_console;
-static struct cyclades_port *serial_console_info = NULL;
-static unsigned int serial_console_cflag = 0;
-u_char initial_console_speed;
-
-/* Base address of cd2401 chip on mvme166/7 */
-
-#define BASE_ADDR (0xfff45000)
-#define pcc2chip ((volatile u_char *)0xfff42000)
-#define PccSCCMICR 0x1d
-#define PccSCCTICR 0x1e
-#define PccSCCRICR 0x1f
-#define PccTPIACKR 0x25
-#define PccRPIACKR 0x27
-#define PccIMLR 0x3f
-
-/* This is the per-port data structure */
-struct cyclades_port cy_port[] = {
- /* CARD# */
- {-1}, /* ttyS0 */
- {-1}, /* ttyS1 */
- {-1}, /* ttyS2 */
- {-1}, /* ttyS3 */
-};
-
-#define NR_PORTS ARRAY_SIZE(cy_port)
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates. The extra
- * are accessed via settings in info->flags.
- * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- * HI VHI
- */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
- 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
- 0
-};
-
-#if 0
-static char baud_co[] = { /* 25 MHz clock option table */
- /* value => 00 01 02 03 04 */
- /* divide by 8 32 128 512 2048 */
- 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
- 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static char baud_bpr[] = { /* 25 MHz baud rate period table */
- 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
- 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-#endif
-
-/* I think 166 brd clocks 2401 at 20MHz.... */
-
-/* These values are written directly to tcor, and >> 5 for writing to rcor */
-static u_char baud_co[] = { /* 20 MHz clock option table */
- 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
- 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* These values written directly to tbpr/rbpr */
-static u_char baud_bpr[] = { /* 20 MHz baud rate period table */
- 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
- 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
-};
-
-static u_char baud_cor4[] = { /* receive threshold */
- 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
- 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
-};
-
-static void shutdown(struct cyclades_port *);
-static int startup(struct cyclades_port *);
-static void cy_throttle(struct tty_struct *);
-static void cy_unthrottle(struct tty_struct *);
-static void config_setup(struct cyclades_port *);
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int);
-#endif
-
-/*
- * I have my own version of udelay(), as it is needed when initialising
- * the chip, before the delay loop has been calibrated. Should probably
- * reference one of the vmechip2 or pccchip2 counter for an accurate
- * delay, but this wild guess will do for now.
- */
-
-void my_udelay(long us)
-{
- u_char x;
- volatile u_char *p = &x;
- int i;
-
- while (us--)
- for (i = 100; i; i--)
- x |= *p;
-}
-
-static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
- const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- if (!info) {
- printk("Warning: null cyclades_port for (%s) in %s\n", name,
- routine);
- return 1;
- }
-
- if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
- printk("Warning: cyclades_port out of range for (%s) in %s\n",
- name, routine);
- return 1;
- }
-
- if (info->magic != CYCLADES_MAGIC) {
- printk("Warning: bad magic number for serial struct (%s) in "
- "%s\n", name, routine);
- return 1;
- }
-#endif
- return 0;
-} /* serial_paranoia_check */
-
-#if 0
-/* The following diagnostic routines allow the driver to spew
- information on the screen, even (especially!) during interrupts.
- */
-void SP(char *data)
-{
- unsigned long flags;
- local_irq_save(flags);
- printk(KERN_EMERG "%s", data);
- local_irq_restore(flags);
-}
-
-char scrn[2];
-void CP(char data)
-{
- unsigned long flags;
- local_irq_save(flags);
- scrn[0] = data;
- printk(KERN_EMERG "%c", scrn);
- local_irq_restore(flags);
-} /* CP */
-
-void CP1(int data)
-{
- (data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
-} /* CP1 */
-void CP2(int data)
-{
- CP1((data >> 4) & 0x0f);
- CP1(data & 0x0f);
-} /* CP2 */
-void CP4(int data)
-{
- CP2((data >> 8) & 0xff);
- CP2(data & 0xff);
-} /* CP4 */
-void CP8(long data)
-{
- CP4((data >> 16) & 0xffff);
- CP4(data & 0xffff);
-} /* CP8 */
-#endif
-
-/* This routine waits up to 1000 micro-seconds for the previous
- command to the Cirrus chip to complete and then issues the
- new command. An error is returned if the previous command
- didn't finish within the time limit.
- */
-u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
-{
- unsigned long flags;
- volatile int i;
-
- local_irq_save(flags);
- /* Check to see that the previous command has completed */
- for (i = 0; i < 100; i++) {
- if (base_addr[CyCCR] == 0) {
- break;
- }
- my_udelay(10L);
- }
- /* if the CCR never cleared, the previous command
- didn't finish within the "reasonable time" */
- if (i == 10) {
- local_irq_restore(flags);
- return (-1);
- }
-
- /* Issue the new command */
- base_addr[CyCCR] = cmd;
- local_irq_restore(flags);
- return (0);
-} /* write_cy_cmd */
-
-/* cy_start and cy_stop provide software output flow control as a
- function of XON/XOFF, software CTS, and other such stuff. */
-
-static void cy_stop(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- int channel;
- unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
- printk("cy_stop %s\n", tty->name); /* */
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_stop"))
- return;
-
- channel = info->line;
-
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char) (channel); /* index channel */
- base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
- local_irq_restore(flags);
-} /* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- int channel;
- unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
- printk("cy_start %s\n", tty->name); /* */
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_start"))
- return;
-
- channel = info->line;
-
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char) (channel);
- base_addr[CyIER] |= CyTxMpty;
- local_irq_restore(flags);
-} /* cy_start */
-
-/* The real interrupt service routines are called
- whenever the card wants its hand held--chars
- received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
-{
- struct tty_struct *tty;
- struct cyclades_port *info;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- unsigned char err, rfoc;
- int channel;
- char data;
-
- /* determine the channel and change to that context */
- channel = (u_short) (base_addr[CyLICR] >> 2);
- info = &cy_port[channel];
- info->last_active = jiffies;
-
- if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
- /* This is a receive timeout interrupt, ignore it */
- base_addr[CyREOIR] = CyNOTRANS;
- return IRQ_HANDLED;
- }
-
- /* Read a byte of data if there is any - assume the error
- * is associated with this character */
-
- if ((rfoc = base_addr[CyRFOC]) != 0)
- data = base_addr[CyRDR];
- else
- data = 0;
-
- /* if there is nowhere to put the data, discard it */
- if (info->tty == 0) {
- base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
- return IRQ_HANDLED;
- } else { /* there is an open port for this data */
- tty = info->tty;
- if (err & info->ignore_status_mask) {
- base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
- return IRQ_HANDLED;
- }
- if (tty_buffer_request_room(tty, 1) != 0) {
- if (err & info->read_status_mask) {
- if (err & CyBREAK) {
- tty_insert_flip_char(tty, data,
- TTY_BREAK);
- if (info->flags & ASYNC_SAK) {
- do_SAK(tty);
- }
- } else if (err & CyFRAME) {
- tty_insert_flip_char(tty, data,
- TTY_FRAME);
- } else if (err & CyPARITY) {
- tty_insert_flip_char(tty, data,
- TTY_PARITY);
- } else if (err & CyOVERRUN) {
- tty_insert_flip_char(tty, 0,
- TTY_OVERRUN);
- /*
- If the flip buffer itself is
- overflowing, we still lose
- the next incoming character.
- */
- if (tty_buffer_request_room(tty, 1) !=
- 0) {
- tty_insert_flip_char(tty, data,
- TTY_FRAME);
- }
- /* These two conditions may imply */
- /* a normal read should be done. */
- /* else if(data & CyTIMEOUT) */
- /* else if(data & CySPECHAR) */
- } else {
- tty_insert_flip_char(tty, 0,
- TTY_NORMAL);
- }
- } else {
- tty_insert_flip_char(tty, data, TTY_NORMAL);
- }
- } else {
- /* there was a software buffer overrun
- and nothing could be done about it!!! */
- }
- }
- tty_schedule_flip(tty);
- /* end of service */
- base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
- return IRQ_HANDLED;
-} /* cy_rxerr_interrupt */
-
-static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
-{
- struct cyclades_port *info;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- int channel;
- int mdm_change;
- int mdm_status;
-
- /* determine the channel and change to that context */
- channel = (u_short) (base_addr[CyLICR] >> 2);
- info = &cy_port[channel];
- info->last_active = jiffies;
-
- mdm_change = base_addr[CyMISR];
- mdm_status = base_addr[CyMSVR1];
-
- if (info->tty == 0) { /* nowhere to put the data, ignore it */
- ;
- } else {
- if ((mdm_change & CyDCD)
- && (info->flags & ASYNC_CHECK_CD)) {
- if (mdm_status & CyDCD) {
-/* CP('!'); */
- wake_up_interruptible(&info->open_wait);
- } else {
-/* CP('@'); */
- tty_hangup(info->tty);
- wake_up_interruptible(&info->open_wait);
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- }
- }
- if ((mdm_change & CyCTS)
- && (info->flags & ASYNC_CTS_FLOW)) {
- if (info->tty->stopped) {
- if (mdm_status & CyCTS) {
- /* !!! cy_start isn't used because... */
- info->tty->stopped = 0;
- base_addr[CyIER] |= CyTxMpty;
- tty_wakeup(info->tty);
- }
- } else {
- if (!(mdm_status & CyCTS)) {
- /* !!! cy_stop isn't used because... */
- info->tty->stopped = 1;
- base_addr[CyIER] &=
- ~(CyTxMpty | CyTxRdy);
- }
- }
- }
- if (mdm_status & CyDSR) {
- }
- }
- base_addr[CyMEOIR] = 0;
- return IRQ_HANDLED;
-} /* cy_modem_interrupt */
-
-static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
-{
- struct cyclades_port *info;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- int channel;
- int char_count, saved_cnt;
- int outch;
-
- /* determine the channel and change to that context */
- channel = (u_short) (base_addr[CyLICR] >> 2);
-
- /* validate the port number (as configured and open) */
- if ((channel < 0) || (NR_PORTS <= channel)) {
- base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
- base_addr[CyTEOIR] = CyNOTRANS;
- return IRQ_HANDLED;
- }
- info = &cy_port[channel];
- info->last_active = jiffies;
- if (info->tty == 0) {
- base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
- base_addr[CyTEOIR] = CyNOTRANS;
- return IRQ_HANDLED;
- }
-
- /* load the on-chip space available for outbound data */
- saved_cnt = char_count = base_addr[CyTFTC];
-
- if (info->x_char) { /* send special char */
- outch = info->x_char;
- base_addr[CyTDR] = outch;
- char_count--;
- info->x_char = 0;
- }
-
- if (info->x_break) {
- /* The Cirrus chip requires the "Embedded Transmit
- Commands" of start break, delay, and end break
- sequences to be sent. The duration of the
- break is given in TICs, which runs at HZ
- (typically 100) and the PPR runs at 200 Hz,
- so the delay is duration * 200/HZ, and thus a
- break can run from 1/100 sec to about 5/4 sec.
- Need to check these values - RGH 141095.
- */
- base_addr[CyTDR] = 0; /* start break */
- base_addr[CyTDR] = 0x81;
- base_addr[CyTDR] = 0; /* delay a bit */
- base_addr[CyTDR] = 0x82;
- base_addr[CyTDR] = info->x_break * 200 / HZ;
- base_addr[CyTDR] = 0; /* terminate break */
- base_addr[CyTDR] = 0x83;
- char_count -= 7;
- info->x_break = 0;
- }
-
- while (char_count > 0) {
- if (!info->xmit_cnt) {
- base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
- break;
- }
- if (info->xmit_buf == 0) {
- base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
- break;
- }
- if (info->tty->stopped || info->tty->hw_stopped) {
- base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
- break;
- }
- /* Because the Embedded Transmit Commands have been
- enabled, we must check to see if the escape
- character, NULL, is being sent. If it is, we
- must ensure that there is room for it to be
- doubled in the output stream. Therefore we
- no longer advance the pointer when the character
- is fetched, but rather wait until after the check
- for a NULL output character. (This is necessary
- because there may not be room for the two chars
- needed to send a NULL.
- */
- outch = info->xmit_buf[info->xmit_tail];
- if (outch) {
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1)
- & (PAGE_SIZE - 1);
- base_addr[CyTDR] = outch;
- char_count--;
- } else {
- if (char_count > 1) {
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1)
- & (PAGE_SIZE - 1);
- base_addr[CyTDR] = outch;
- base_addr[CyTDR] = 0;
- char_count--;
- char_count--;
- } else {
- break;
- }
- }
- }
-
- if (info->xmit_cnt < WAKEUP_CHARS)
- tty_wakeup(info->tty);
-
- base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
- return IRQ_HANDLED;
-} /* cy_tx_interrupt */
-
-static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
-{
- struct tty_struct *tty;
- struct cyclades_port *info;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- int channel;
- char data;
- int char_count;
- int save_cnt;
-
- /* determine the channel and change to that context */
- channel = (u_short) (base_addr[CyLICR] >> 2);
- info = &cy_port[channel];
- info->last_active = jiffies;
- save_cnt = char_count = base_addr[CyRFOC];
-
- /* if there is nowhere to put the data, discard it */
- if (info->tty == 0) {
- while (char_count--) {
- data = base_addr[CyRDR];
- }
- } else { /* there is an open port for this data */
- tty = info->tty;
- /* load # characters available from the chip */
-
-#ifdef CYCLOM_ENABLE_MONITORING
- ++info->mon.int_count;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
-#endif
- while (char_count--) {
- data = base_addr[CyRDR];
- tty_insert_flip_char(tty, data, TTY_NORMAL);
-#ifdef CYCLOM_16Y_HACK
- udelay(10L);
-#endif
- }
- tty_schedule_flip(tty);
- }
- /* end of service */
- base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
- return IRQ_HANDLED;
-} /* cy_rx_interrupt */
-
-/* This is called whenever a port becomes active;
- interrupts are enabled and DTR & RTS are turned on.
- */
-static int startup(struct cyclades_port *info)
-{
- unsigned long flags;
- volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
- int channel;
-
- if (info->flags & ASYNC_INITIALIZED) {
- return 0;
- }
-
- if (!info->type) {
- if (info->tty) {
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- return 0;
- }
- if (!info->xmit_buf) {
- info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
- if (!info->xmit_buf) {
- return -ENOMEM;
- }
- }
-
- config_setup(info);
-
- channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("startup channel %d\n", channel);
-#endif
-
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char) channel;
- write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
- base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */
- base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('1'); */
- base_addr[CyMSVR2] = CyDTR;
-
-#ifdef SERIAL_DEBUG_DTR
- printk("cyc: %d: raising DTR\n", __LINE__);
- printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
- base_addr[CyMSVR2]);
-#endif
-
- base_addr[CyIER] |= CyRxData;
- info->flags |= ASYNC_INITIALIZED;
-
- if (info->tty) {
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
- local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
- printk(" done\n");
-#endif
- return 0;
-} /* startup */
-
-void start_xmit(struct cyclades_port *info)
-{
- unsigned long flags;
- volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
- int channel;
-
- channel = info->line;
- local_irq_save(flags);
- base_addr[CyCAR] = channel;
- base_addr[CyIER] |= CyTxMpty;
- local_irq_restore(flags);
-} /* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct cyclades_port *info)
-{
- unsigned long flags;
- volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
- int channel;
-
- if (!(info->flags & ASYNC_INITIALIZED)) {
-/* CP('$'); */
- return;
- }
-
- channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("shutdown channel %d\n", channel);
-#endif
-
- /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
- SENT BEFORE DROPPING THE LINE !!! (Perhaps
- set some flag that is read when XMTY happens.)
- Other choices are to delay some fixed interval
- or schedule some later processing.
- */
- local_irq_save(flags);
- if (info->xmit_buf) {
- free_page((unsigned long)info->xmit_buf);
- info->xmit_buf = NULL;
- }
-
- base_addr[CyCAR] = (u_char) channel;
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
- base_addr[CyMSVR1] = 0;
-/* CP('C');CP('1'); */
- base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
- printk("cyc: %d: dropping DTR\n", __LINE__);
- printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
- base_addr[CyMSVR2]);
-#endif
- }
- write_cy_cmd(base_addr, CyDIS_RCVR);
- /* it may be appropriate to clear _XMIT at
- some later date (after testing)!!! */
-
- if (info->tty) {
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- info->flags &= ~ASYNC_INITIALIZED;
- local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
- printk(" done\n");
-#endif
-} /* shutdown */
-
-/*
- * This routine finds or computes the various line characteristics.
- */
-static void config_setup(struct cyclades_port *info)
-{
- unsigned long flags;
- volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
- int channel;
- unsigned cflag;
- int i;
- unsigned char ti, need_init_chan = 0;
-
- if (!info->tty || !info->tty->termios) {
- return;
- }
- if (info->line == -1) {
- return;
- }
- cflag = info->tty->termios->c_cflag;
-
- /* baud rate */
- i = cflag & CBAUD;
-#ifdef CBAUDEX
-/* Starting with kernel 1.1.65, there is direct support for
- higher baud rates. The following code supports those
- changes. The conditional aspect allows this driver to be
- used for earlier as well as later kernel versions. (The
- mapping is slightly different from serial.c because there
- is still the possibility of supporting 75 kbit/sec with
- the Cyclades board.)
- */
- if (i & CBAUDEX) {
- if (i == B57600)
- i = 16;
- else if (i == B115200)
- i = 18;
-#ifdef B78600
- else if (i == B78600)
- i = 17;
-#endif
- else
- info->tty->termios->c_cflag &= ~CBAUDEX;
- }
-#endif
- if (i == 15) {
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- i += 1;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- i += 3;
- }
- /* Don't ever change the speed of the console port. It will
- * run at the speed specified in bootinfo, or at 19.2K */
- /* Actually, it should run at whatever speed 166Bug was using */
- /* Note info->timeout isn't used at present */
- if (info != serial_console_info) {
- info->tbpr = baud_bpr[i]; /* Tx BPR */
- info->tco = baud_co[i]; /* Tx CO */
- info->rbpr = baud_bpr[i]; /* Rx BPR */
- info->rco = baud_co[i] >> 5; /* Rx CO */
- if (baud_table[i] == 134) {
- info->timeout =
- (info->xmit_fifo_size * HZ * 30 / 269) + 2;
- /* get it right for 134.5 baud */
- } else if (baud_table[i]) {
- info->timeout =
- (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
- 2;
- /* this needs to be propagated into the card info */
- } else {
- info->timeout = 0;
- }
- }
- /* By tradition (is it a standard?) a baud rate of zero
- implies the line should be/has been closed. A bit
- later in this routine such a test is performed. */
-
- /* byte size and parity */
- info->cor7 = 0;
- info->cor6 = 0;
- info->cor5 = 0;
- info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]); /* receive threshold */
- /* Following two lines added 101295, RGH. */
- /* It is obviously wrong to access CyCORx, and not info->corx here,
- * try and remember to fix it later! */
- channel = info->line;
- base_addr[CyCAR] = (u_char) channel;
- if (C_CLOCAL(info->tty)) {
- if (base_addr[CyIER] & CyMdmCh)
- base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */
- /* ignore 1->0 modem transitions */
- if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
- base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
- /* ignore 0->1 modem transitions */
- if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
- base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
- } else {
- if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
- base_addr[CyIER] |= CyMdmCh; /* with modem intr */
- /* act on 1->0 modem transitions */
- if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
- (CyDSR | CyCTS | CyDCD))
- base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
- /* act on 0->1 modem transitions */
- if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
- (CyDSR | CyCTS | CyDCD))
- base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
- }
- info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
- info->cor2 = CyETC;
- switch (cflag & CSIZE) {
- case CS5:
- info->cor1 = Cy_5_BITS;
- break;
- case CS6:
- info->cor1 = Cy_6_BITS;
- break;
- case CS7:
- info->cor1 = Cy_7_BITS;
- break;
- case CS8:
- info->cor1 = Cy_8_BITS;
- break;
- }
- if (cflag & PARENB) {
- if (cflag & PARODD) {
- info->cor1 |= CyPARITY_O;
- } else {
- info->cor1 |= CyPARITY_E;
- }
- } else {
- info->cor1 |= CyPARITY_NONE;
- }
-
- /* CTS flow control flag */
-#if 0
- /* Don't complcate matters for now! RGH 141095 */
- if (cflag & CRTSCTS) {
- info->flags |= ASYNC_CTS_FLOW;
- info->cor2 |= CyCtsAE;
- } else {
- info->flags &= ~ASYNC_CTS_FLOW;
- info->cor2 &= ~CyCtsAE;
- }
-#endif
- if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
- else
- info->flags |= ASYNC_CHECK_CD;
-
- /***********************************************
- The hardware option, CyRtsAO, presents RTS when
- the chip has characters to send. Since most modems
- use RTS as reverse (inbound) flow control, this
- option is not used. If inbound flow control is
- necessary, DTR can be programmed to provide the
- appropriate signals for use with a non-standard
- cable. Contact Marcio Saito for details.
- ***********************************************/
-
- channel = info->line;
-
- local_irq_save(flags);
- base_addr[CyCAR] = (u_char) channel;
-
- /* CyCMR set once only in mvme167_init_serial() */
- if (base_addr[CyLICR] != channel << 2)
- base_addr[CyLICR] = channel << 2;
- if (base_addr[CyLIVR] != 0x5c)
- base_addr[CyLIVR] = 0x5c;
-
- /* tx and rx baud rate */
-
- if (base_addr[CyCOR1] != info->cor1)
- need_init_chan = 1;
- if (base_addr[CyTCOR] != info->tco)
- base_addr[CyTCOR] = info->tco;
- if (base_addr[CyTBPR] != info->tbpr)
- base_addr[CyTBPR] = info->tbpr;
- if (base_addr[CyRCOR] != info->rco)
- base_addr[CyRCOR] = info->rco;
- if (base_addr[CyRBPR] != info->rbpr)
- base_addr[CyRBPR] = info->rbpr;
-
- /* set line characteristics according configuration */
-
- if (base_addr[CySCHR1] != START_CHAR(info->tty))
- base_addr[CySCHR1] = START_CHAR(info->tty);
- if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
- base_addr[CySCHR2] = STOP_CHAR(info->tty);
- if (base_addr[CySCRL] != START_CHAR(info->tty))
- base_addr[CySCRL] = START_CHAR(info->tty);
- if (base_addr[CySCRH] != START_CHAR(info->tty))
- base_addr[CySCRH] = START_CHAR(info->tty);
- if (base_addr[CyCOR1] != info->cor1)
- base_addr[CyCOR1] = info->cor1;
- if (base_addr[CyCOR2] != info->cor2)
- base_addr[CyCOR2] = info->cor2;
- if (base_addr[CyCOR3] != info->cor3)
- base_addr[CyCOR3] = info->cor3;
- if (base_addr[CyCOR4] != info->cor4)
- base_addr[CyCOR4] = info->cor4;
- if (base_addr[CyCOR5] != info->cor5)
- base_addr[CyCOR5] = info->cor5;
- if (base_addr[CyCOR6] != info->cor6)
- base_addr[CyCOR6] = info->cor6;
- if (base_addr[CyCOR7] != info->cor7)
- base_addr[CyCOR7] = info->cor7;
-
- if (need_init_chan)
- write_cy_cmd(base_addr, CyINIT_CHAN);
-
- base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */
-
- /* 2ms default rx timeout */
- ti = info->default_timeout ? info->default_timeout : 0x02;
- if (base_addr[CyRTPRL] != ti)
- base_addr[CyRTPRL] = ti;
- if (base_addr[CyRTPRH] != 0)
- base_addr[CyRTPRH] = 0;
-
- /* Set up RTS here also ????? RGH 141095 */
- if (i == 0) { /* baud rate is zero, turn off line */
- if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
- base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
- printk("cyc: %d: dropping DTR\n", __LINE__);
- printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
- base_addr[CyMSVR2]);
-#endif
- } else {
- if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
- base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
- printk("cyc: %d: raising DTR\n", __LINE__);
- printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
- base_addr[CyMSVR2]);
-#endif
- }
-
- if (info->tty) {
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- }
-
- local_irq_restore(flags);
-
-} /* config_setup */
-
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct cyclades_port *info = tty->driver_data;
- unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
- printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_put_char"))
- return 0;
-
- if (!info->xmit_buf)
- return 0;
-
- local_irq_save(flags);
- if (info->xmit_cnt >= PAGE_SIZE - 1) {
- local_irq_restore(flags);
- return 0;
- }
-
- info->xmit_buf[info->xmit_head++] = ch;
- info->xmit_head &= PAGE_SIZE - 1;
- info->xmit_cnt++;
- local_irq_restore(flags);
- return 1;
-} /* cy_put_char */
-
-static void cy_flush_chars(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- unsigned long flags;
- volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
- int channel;
-
-#ifdef SERIAL_DEBUG_IO
- printk("cy_flush_chars %s\n", tty->name); /* */
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
- return;
-
- if (info->xmit_cnt <= 0 || tty->stopped
- || tty->hw_stopped || !info->xmit_buf)
- return;
-
- channel = info->line;
-
- local_irq_save(flags);
- base_addr[CyCAR] = channel;
- base_addr[CyIER] |= CyTxMpty;
- local_irq_restore(flags);
-} /* cy_flush_chars */
-
-/* This routine gets called when tty_write has put something into
- the write_queue. If the port is not already transmitting stuff,
- start it off by enabling interrupts. The interrupt service
- routine will then ensure that the characters are sent. If the
- port is already active, there is no need to kick it.
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
- struct cyclades_port *info = tty->driver_data;
- unsigned long flags;
- int c, total = 0;
-